/*
* 坐标结构
*/
class FCPoint {
	public x : number; //横坐标
	public y : number; //纵坐标
	// 构造函数
	constructor(ix : number, iy : number) {
		this.x = ix;
		this.y = iy;
	}
}

/*
* 大小结构
*/
class FCSize {
	public cx : number; //长
	public cy : number; //宽
	// 构造函数
	constructor(icx : number, icy : number) {
		this.cx = icx;
		this.cy = icy;
	}
}

/*
* 矩形结构
*/
class FCRect {
	public left : number; //左侧
	public top : number; //上侧
	public right : number; //右侧
	public bottom : number; //底部
	// 构造函数
	constructor(ileft : number, itop : number, iright : number, ibottom : number) {
		this.left = ileft;
		this.top = itop;
		this.right = iright;
		this.bottom = ibottom;
	}
}

/*
* 边距信息
*/
class FCPadding {
	public left : number; //左侧
	public top : number; //上侧
	public right : number; //右侧
	public bottom : number; //底部
	// 构造函数
	constructor(ileft : number, itop : number, iright : number, ibottom : number) {
		this.left = ileft;
		this.top = itop;
		this.right = iright;
		this.bottom = ibottom;
	}
}

/*
* 转换颜色
*/
function convertColor(inColor : string) : string {
	if (inColor.indexOf("rgba(") != -1) {
		let inStrs = inColor.replace("rgba(", "").replace(")", "");
		let strs = inStrs.split(',');
		if (strs.length >= 4) {
			let a = strToNumber(strs[3]);
			a /= 255;
			return "rgba(" + strs[0] + "," + strs[1] + "," + strs[2] + "," + a + ")";
		}
	}
	return inColor;
}

function strToNumber(str : string) : number {
	return parseFloat(str);
}

type ClickTreeNodeEventCallBack = (tree : FCTree, node : FCTreeNode, firstTouch : boolean, firstPoint : FCPoint, secondTouch : boolean, secondPoint : FCPoint, clicks : number) => void;
type ClickGridCellEventCallBack = (grid : FCGrid, row : FCGridRow, gridColumn : FCGridColumn, cell : FCGridCell, firstTouch : boolean, firstPoint : FCPoint, secondTouch : boolean, secondPoint : FCPoint, clicks : number) => void;
type ClickGridColumnEventCallBack = (grid : FCGrid, gridColumn : FCGridColumn, firstTouch : boolean, firstPoint : FCPoint, secondTouch : boolean, secondPoint : FCPoint, clicks : number) => void;
type CalculateChartMaxMinEventCallBack = (chart : FCChart) => void;
type InvalidateEventCallBack = (paint : FCPaint) => void;
type InvalidateViewEventCallBack = (view : FCView) => void;
type ClickEventCallBack = (view : FCView, firstTouch : boolean, firstPoint : FCPoint, secondTouch : boolean, secondPoint : FCPoint, clicks : number) => void;
type PaintEventCallBack = (view : FCView, paint : FCPaint, clipRect : FCRect) => void;
type PaintGridCellEventCallBack = (grid : FCGrid, row : FCGridRow, column : FCGridColumn, cell : FCGridCell, paint : FCPaint, left : number, top : number, right : number, bottom : number) => void;
type PaintGridColumnEventCallBack = (grid : FCGrid, column : FCGridColumn, paint : FCPaint, left : number, top : number, right : number, bottom : number) => void;
type PaintTreeNodeEventCallBack = (tree : FCTree, row : FCTreeRow, column : FCTreeColumn, node : FCTreeNode, paint : FCPaint, left : number, top : number, right : number, bottom : number) => void;
type PaintCalendarDayButtonEventCallBack = (calendar : FCCalendar, dayButton : DayButton, paint : FCPaint) => void;
type PaintCalendarMonthButtonEventCallBack = (calendar : FCCalendar, monthButton : MonthButton, paint : FCPaint) => void;
type PaintCalendarYearButtonEventCallBack = (calendar : FCCalendar, yearButton : YearButton, paint : FCPaint) => void;
type PaintCalendarHeadDivEventCallBack = (calendar : FCCalendar, headDiv : HeadDiv, paint : FCPaint) => void;
type RenderViewsEventCallBack = (views : Array<FCView>, paint : FCPaint, clipRect : FCRect) => void;
type TouchEventCallBack = (view : FCView, firstTouch : boolean, firstPoint : FCPoint, secondTouch : boolean, secondPoint : FCPoint) => void;
type UpdateViewEventCallBack = (views : Array<FCView>) => void;
type ContainsPointCallBack = (view:FCView, mp:FCPoint) => boolean;

/*
* 绘图结构
*/
class FCPaint {
	public cancelClick : boolean = false; //是否退出点击
	public context : DrawableContext | null = null;//绘图上下文
	public defaultUIStyle : string = "light"; //默认样式
	public dragBeginPoint : FCPoint = new FCPoint(0, 0); //拖动开始时的触摸位置
	public dragBeginRect : FCRect = new FCRect(0, 0, 0, 0); //拖动开始时的区域
	public draggingView : FCView | null = null; //正被拖动的控件
	public firstTouch : boolean = false;
	public focusedView : FCView | null = null; //焦点视图
	public isDoubleClick: boolean = false; //是否双击
	public isMobile : boolean = true;
	public isPath : boolean = false; //是否路径
	public lastClickTime:number = 0; //上次点击时间
	public moveTo : boolean = false;
	public offsetX : number = 0.0; //横向偏移
	public offsetY : number = 0.0; //纵向偏移
	public ratio : number = 1; //缩放比例
	public resizeColumnState : number = 0.0; //改变列宽度的状态
	public resizeColumnBeginWidth : number = 0.0; //改变列宽度的起始值
	public resizeColumnIndex : number = -1; //改变列宽度的索引
	public scaleFactorX : number = 1.0; //横向缩放比例
	public scaleFactorY : number = 1.0; //纵向缩放比例
	public secondTouch : boolean = false;
	public size : FCSize = new FCSize(0, 0);
	public systemFont : string = "Arial"; //系统字体
	public touchDownPoint : FCPoint = new FCPoint(0, 0);
	public touchFirstPoint : FCPoint = new FCPoint(0, 0);
	public touchSecondPoint : FCPoint = new FCPoint(0, 0);
	public touchDownView : FCView | null = null; //鼠标按下的视图
	public touchMoveView : FCView | null = null; //鼠标移动的视图
	public views : Array<FCView> = [];
	public onClickGridCell : ClickGridCellEventCallBack | null = null; //点击单元格的回调
	public onClickGridColumn : ClickGridColumnEventCallBack | null = null; //点击列的回调
	public onClickTreeNode : ClickTreeNodeEventCallBack | null = null; //点击树节点的回调
	public onCalculateChartMaxMin : CalculateChartMaxMinEventCallBack | null = null; //计算最大最小值的回调
	public onInvalidate : InvalidateEventCallBack | null = null;
	public onInvalidateView : InvalidateViewEventCallBack | null = null;
	public onPaint : PaintEventCallBack | null = null; //重绘回调
	public onPaintBorder : PaintEventCallBack | null = null; //重绘边线回调
	public onPaintGridCell : PaintGridCellEventCallBack | null = null; //绘制单元格的回调
	public onPaintGridColumn : PaintGridColumnEventCallBack | null = null; //绘制表格列的回调
	public onPaintTreeNode : PaintTreeNodeEventCallBack | null = null; //绘制树节点的回调
	public onPaintChartScale : PaintEventCallBack | null = null; //绘制坐标轴回调
	public onPaintChartHScale : PaintEventCallBack | null = null; //绘制坐标轴回调
	public onPaintChartStock : PaintEventCallBack | null = null; //绘制图表回调
	public onPaintChartPlot : PaintEventCallBack | null = null; //绘制画线回调
	public onPaintChartCrossLine : PaintEventCallBack | null = null; //绘制十字线回调
	public onPaintCalendarDayButton : PaintCalendarDayButtonEventCallBack | null = null;
	public onPaintCalendarMonthButton : PaintCalendarMonthButtonEventCallBack | null = null;
	public onPaintCalendarYearButton : PaintCalendarYearButtonEventCallBack | null = null;
	public onPaintHeadDiv : PaintCalendarHeadDivEventCallBack | null = null;
	public onRenderViews : RenderViewsEventCallBack | null = null;
	public onUpdateView : UpdateViewEventCallBack | null = null; //更新布局的回调
	public onContainsPoint: ContainsPointCallBack = null as any;//是否包含坐标
	/*
	* 添加线
	* x1:横坐标1
	* y1:纵坐标1
	* x2:横坐标2
	* y2:纵坐标2
	*/
	addLine(x1 : number, y1 : number, x2 : number, y2 : number) {
		if (!this.moveTo) {
			this.moveTo = true;
			this.context!.moveTo(Math.round((x1 + this.offsetX) * this.scaleFactorX), Math.round((y1 + this.offsetY) * this.scaleFactorY));
		}
		this.context!.lineTo(Math.round((x2 + this.offsetX) * this.scaleFactorX), Math.round((y2 + this.offsetY) * this.scaleFactorY));
	}
	/*
	* 开始路径
	*/
	beginPath() {
		this.context!.beginPath();
		this.isPath = true;
	}
	/*
	* 开始绘图
	* rect:区域
	*/
	beginPaint(rect : FCRect | null) {
		this.context!.reset()
		this.moveTo = false;
		this.offsetX = 0;
		this.offsetY = 0;
	}
	/*
	* 闭合路径
	*/
	closeFigure() {
		this.context!.closePath();
	}
	/*
	* 关闭路径
	*/
	closePath() {
		this.moveTo = false;
	}
	/*
	* 绘制线
	* color:颜色
	* width:宽度
	* style:样式
	* x1:横坐标1
	* y1:纵坐标1
	* x2:横坐标2
	* y2:纵坐标2
	*/
	drawLine(color : string, width : number, style : number[] | null, x1 : number, y1 : number, x2 : number, y2 : number) {
		width = Math.min(this.scaleFactorX, this.scaleFactorY) * width;
		this.context!.beginPath();
		this.context!.strokeStyle = convertColor(color);
		if (this.context!.lineWidth < 1) {
			this.context!.lineWidth = 1;
		}
		if (style != null) {
			this.context!.setLineDash(style);
		}
		this.context!.moveTo(Math.round((x1 + this.offsetX) * this.scaleFactorX), Math.round((y1 + this.offsetY) * this.scaleFactorY));
		this.context!.lineTo(Math.round((x2 + this.offsetX) * this.scaleFactorX), Math.round((y2 + this.offsetY) * this.scaleFactorY));
		this.context!.stroke();
		if (style != null) {
			this.context!.setLineDash([]);
		}
	}
	/*
	* 绘制路径
	* color:颜色
	* width:宽度
	* style:样式
	*/
	drawPath(color : string, width : number, style : number[] | null) {
		width = Math.min(this.scaleFactorX, this.scaleFactorY) * width;
		if (style != null) {
			this.context!.setLineDash(style);
		}
		this.context!.strokeStyle = convertColor(color);
		if (this.context!.lineWidth < 1) {
			this.context!.lineWidth = 1;
		}
		this.context!.stroke();
		if (style != null) {
			this.context!.setLineDash([]);
		}
	}
	/*
	* 绘制连续线条
	* color:颜色
	* width:宽度
	* style:样式
	*/
	drawPolyline(color: string, width: number, style: number[], apt:FCPoint[]) {
		if(apt.length > 1){
			width = Math.min(this.scaleFactorX, this.scaleFactorY) * width;
			if (style) {
				this.context.setLineDash(style);
			}
			this.context.strokeStyle = convertColor(color);
			if (this.context.lineWidth < 1) {
				this.context.lineWidth = 1;
			}
			this.context.beginPath();
			for(let i = 0; i < apt.length; i++){
				let x = apt[i].x;
				let y = apt[i].y;
				x = x + this.offsetX;
				y = y + this.offsetY;
				if (this.scaleFactorX != 1 || this.scaleFactorY != 1){
					x = this.scaleFactorX * x;
					y = this.scaleFactorY * y;
				}
				if (i == 0){
					this.context.moveTo(Math.round(x), Math.round(y));
				}else{
					this.context.lineTo(Math.round(x), Math.round(y));
				}
			}
			this.context.stroke();
			if (style) {
				this.context.setLineDash([]);
			}
		}
	}
	/*
	* 绘制多边形
	* color:颜色
	* width:宽度
	* style:样式
	*/
	drawPolygon(color: string, width: number, style: number[], apt:FCPoint[]) {
		if(apt.length > 1){
			width = Math.min(this.scaleFactorX, this.scaleFactorY) * width;
			if (style) {
				this.context.setLineDash(style);
			}
			this.context.strokeStyle = convertColor(color);
			if (this.context.lineWidth < 1) {
				this.context.lineWidth = 1;
			}
			this.context.beginPath();
			for(let i = 0; i < apt.length; i++){
				let x = apt[i].x;
				let y = apt[i].y;
				x = x + this.offsetX;
				y = y + this.offsetY;
				if (this.scaleFactorX != 1 || this.scaleFactorY != 1){
					x = this.scaleFactorX * x;
					y = this.scaleFactorY * y;
				}
				if (i == 0){
					this.context.moveTo(Math.round(x), Math.round(y));
				}else{
					this.context.lineTo(Math.round(x), Math.round(y));
				}
			}
			this.context.closePath();
			this.context.stroke();
			if (style) {
				this.context.setLineDash([]);
			}
		}
	}
	/*
	* 绘制矩形
	* color:颜色
	* width:宽度
	* style:样式
	* left:左侧坐标
	* top:上方坐标
	* right:右侧坐标
	* bottom:下方坐标
	*/
	drawRect(color : string, width : number, style : number[] | null, left : number, top : number, right : number, bottom : number) {
		width = Math.min(this.scaleFactorX, this.scaleFactorY) * width;
		let w = right - left;
		let h = bottom - top;
		if (style != null) {
			this.context!.setLineDash(style);
		}
		this.context!.strokeStyle = convertColor(color);
		if (this.context!.lineWidth < 1) {
			this.context!.lineWidth = 1;
		}
		this.context!.strokeRect(Math.round((left + this.offsetX) * this.scaleFactorX), Math.round((top + this.offsetY) * this.scaleFactorY), Math.round(w * this.scaleFactorX), Math.round(h * this.scaleFactorY));
		if (style != null) {
			this.context!.setLineDash([]);
		}
	}
	/*
	* 绘制椭圆
	* color:颜色
	* width:宽度
	* style:样式
	* left:左侧坐标
	* top:上方坐标
	* right:右侧坐标
	* bottom:下方坐标
	*/
	drawEllipse(color : string, width : number, style : number[] | null, left : number, top : number, right : number, bottom : number) {
		this.drawRect(color, width, style, left, top, right, bottom);
	}
	/*
	* 绘制圆角矩形
	* color:颜色
	* left:左侧坐标
	* top:上方坐标
	* right:右侧坐标
	* bottom:下方坐标
	* cornerRadius:圆角度数
	*/
	drawRoundRect(color : string, width : number, style : number[] | null, left : number, top : number, right : number, bottom : number, cornerRadius : number) {
		this.drawRect(color, width, style, left, top, right, bottom);
	}
	/*
	* 绘制文字
	* text:文字
	* color:颜色
	* font:字体
	* x:横坐标
	* y:纵坐标
	*/
	drawText(text : string, color : string, font : string, x : number, y : number) {
		if (text != null && text.length != 0 && font != null) {
			let strs = font.split(',');
			let fontFamily = strs[0];
			if (fontFamily == "Default") {
				fontFamily = this.systemFont;
			}
			let sFont = parseInt(strs[1]) + "px " + fontFamily;
			if (this.scaleFactorX != 1 || this.scaleFactorY != 1) {
				sFont = Math.floor((this.scaleFactorX + this.scaleFactorY) / 2 * Math.floor(strToNumber(strs[1]))) + "px " + fontFamily;
			}
			for (let i = 2; i < strs.length; i++) {
				let iStr = strs[i].toLowerCase();
				if (iStr == "bold" || iStr == "italic") {
					sFont = iStr + " " + sFont;
				}
			}
			this.context!.font = sFont;
			this.context!.fillStyle = convertColor(color);
			this.context!.textAlign = 'left';
			let tSize = this.textSize(text, font);
			//this.context!.textBaseline = 'top';
			this.context!.fillText(text, Math.round((x + this.offsetX) * this.scaleFactorX), Math.round((y + this.offsetY + tSize.cy / 2) * this.scaleFactorY));
		}
	}
	/*
	* 结束绘图
	*/
	endPaint() {
		this.context!.update()
	}
	/*
	* 填充路径
	* color:颜色
	*/
	fillPath(color : string) {
		this.context!.fillStyle = convertColor(color);
		this.context!.fill();
	}
	/*
	* 填充多边形
	* color:颜色
	* width:宽度
	* style:样式
	*/
	fillPolygon(color: string, apt:FCPoint[]) {
		if(apt.length > 1){
			this.context.beginPath();
			for(let i = 0; i < apt.length; i++){
				let x = apt[i].x;
				let y = apt[i].y;
				x = x + this.offsetX;
				y = y + this.offsetY;
				if (this.scaleFactorX != 1 || this.scaleFactorY != 1){
					x = this.scaleFactorX * x;
					y = this.scaleFactorY * y;
				}
				if (i == 0){
					this.context.moveTo(Math.round(x), Math.round(y));
				}else{
					this.context.lineTo(Math.round(x), Math.round(y));
				}
			}
			this.context.fillStyle = convertColor(color);
			this.context.closePath();
			this.context.fill();
		}
	}
	/*
	* 填充矩形
	* color:颜色
	* left:左侧坐标
	* top:上方坐标
	* right:右侧坐标
	* bottom:下方坐标
	*/
	fillRect(color : string, left : number, top : number, right : number, bottom : number) {
		let w = right - left;
		let h = bottom - top;
		this.context!.fillStyle = convertColor(color);
		this.context!.fillRect(Math.round((left + this.offsetX) * this.scaleFactorX), Math.round((top + this.offsetY) * this.scaleFactorY), Math.round(w * this.scaleFactorX), Math.round(h * this.scaleFactorY));
	}
	/*
	* 填充圆角矩形
	* color:颜色
	* left:左侧坐标
	* top:上方坐标
	* right:右侧坐标
	* bottom:下方坐标
	* cornerRadius:圆角度数
	*/
	fillRoundRect(color : string, left : number, top : number, right : number, bottom : number, cornerRadius : number) {
		this.fillRect(color, left, top, right, bottom);
	}
	/*
	* 填充椭圆
	* color:颜色
	* left:左侧坐标
	* top:上方坐标
	* right:右侧坐标
	* bottom:下方坐标
	*/
	fillEllipse(color : string, left : number, top : number, right : number, bottom : number) {
		this.fillRect(color, left, top, right, bottom);
	}
	/*
	* 裁剪
	* left:左侧坐标
	* top:上方坐标
	* right:右侧坐标
	* bottom:下方坐标
	*/
	setClip(left : number, top : number, right : number, bottom : number) {
		let w = right - left;
		let h = bottom - top;
		this.context!.beginPath();
		this.context!.rect(Math.round((left + this.offsetX) * this.scaleFactorX), Math.round((top + this.offsetY) * this.scaleFactorY), Math.round(w * this.scaleFactorX), Math.round(h * this.scaleFactorY));
		//this.context!.clip();
	}
	/*
	* 设置偏移量
	* offsetX:横向偏移
	* offsetY:纵向偏移
	*/
	setOffset(x : number, y : number) {
		this.offsetX = x;
		this.offsetY = y;
	}
	/*
	* 获取字体大小
	* text:文字
	* font:字体
	*/
	textSize(text : string, font : string) : FCSize {
		if (text != null && text.length != 0 && font != null) {
			let strs = font.split(',');
			return new FCSize(parseInt(strs[1]) * text.length / 2, parseInt(strs[1]) / 4);
		} else {
			return new FCSize(0, 0);
		}
	}
	/*
	* 保存状态
	*/
	save() {
	}
	/*
	* 恢复状态
	*/
	restore() {
	}
	/*
	* 绘制文字
	* text:文字
	* color:颜色
	* font:字体
	* left:左侧坐标
	* top:上方坐标
	* right:右侧坐标
	* bottom:下方坐标
	*/
	drawTextAutoEllipsis(text : string, color : string, font : string, left : number, top : number, right : number, bottom : number) {
		if (text.length != 0) {
			let tSize = this.textSize(text, font);
			if (tSize.cx < right - left) {
				this.drawText(text, color, font, left, top);
			} else {
				if (tSize.cx > 0) {
					let subLen = 3;
					while (true) {
						let newLen = text.length - subLen;
						if (newLen > 0) {
							let newText = text.substring(0, newLen) + "...";
							tSize = this.textSize(newText, font);
							if (tSize.cx < right - left) {
								this.drawText(newText, color, font, left, top);

								break;
							} else {
								subLen += 3;
							}
						} else {
							break;
						}
					}
				}
			}
		}
	}
}

/*
* 基础视图
*/
class FCView {
	public allowDrag : boolean = false; //是否允许拖动
	public allowResize : boolean = false; //是否可以拖动改变大小
	public align : string = "left"; //横向布局
	public allowDragScroll : boolean = true; //是否允许拖动滚动
	public allowPreviewsEvent : boolean = false; //是否允许预处理事件
	public backColor : string = "rgb(255,255,255)"; //背景色
	public borderColor: string = "rgb(150,150,150)"; //边线色
	public borderWidth: number = 1; //边线宽度
	public clipRect : FCRect = new FCRect(0, 0, 0, 0); //裁剪区域
	public cornerRadius : number = 0; //圆角
	public downScrollHButton : boolean = false; //是否按下横向滚动条
	public downScrollVButton : boolean = false; //是否按下纵向滚动条
	public displayOffset : boolean = true; //是否显示偏移量
	public dock : string = "none"; //悬浮状态
	public enabled : boolean = true; //是否可用
	public exAttributes : Map<string, string> = new Map<string, string>(); //额外属性
	public font : string = "Default,12"; //字体
	public hoveredColor : string | null = null; //鼠标悬停时的颜色
	public hoverScrollHButton : boolean = false;  //是否悬停横向滚动条
	public hoverScrollVButton : boolean = false;  //是否悬停纵向滚动条
	public hScrollIsVisible : boolean = false; //横向滚动是否显示
	public location : FCPoint = new FCPoint(0, 0); //坐标
	public margin : FCPadding = new FCPadding(0, 0, 0, 0);  //外边距
	public maximumSize : FCSize = new FCSize(0, 0); //最大大小
	public padding : FCPadding = new FCPadding(0, 0, 0, 0); //内边距
	public paint : FCPaint | null = null; //绘图对象
	public parent : FCView | null = null;  //父视图
	public pushedColor : string = "rgb(100,100,100)"; //鼠标按下时的颜色
	public resizePoint : number = -1; //调整尺寸的点
	public scrollV : number = 0.0; //纵向滚动
	public scrollH : number = 0.0; //横向滚动
	public scrollSize : number = 8.0; //滚动条的大小
	public showHScrollBar : boolean = false; //是否显示横向滚动条
	public showVScrollBar : boolean = false; //是否显示横向滚动条
	public scrollBarColor : string = "rgb(200,200,200)"; //滚动条的颜色
	public scrollBarHoveredColor : string = "rgb(42,138,195)"; //滚动条悬停的颜色
	public size : FCSize = new FCSize(0, 0); //大小
	public startScrollH : number = 0.0; //开始滚动的值
	public startScrollV : number = 0.0; //结束滚动的值
	public startPoint : FCPoint = new FCPoint(0, 0); //起始点
	public startRect : FCRect = new FCRect(0, 0, 0, 0); //移动开始时的视图矩形
	public tabIndex:number = 0; //Tab索引
  	public tabStop:boolean = false; //是否支持Tab
	public text : string = ""; //文字
	public textColor : string = "rgb(0,0,0)"; //前景色
	public topMost : boolean = false; //是否置顶
	public touchDownTime : number = 0; //鼠标按下的时间
	public viewName : string = ""; //名称
	public visible : boolean = true; //可见性
	public verticalAlign : string = "top"; //纵向布局
	public viewType : string = "none"; //类型
	public vScrollIsVisible : boolean = false; //纵向滚动是否显示
	public views : Array<FCView> = [];
	// 构造函数
	constructor() {
	}
}

/*
* 按钮
*/
class FCButton extends FCView {
	// 构造函数
	constructor() {
		super();
		super.viewType = "button";
		super.hoveredColor = "rgb(150,150,150)";
		super.pushedColor = "rgb(200,200,200)";
	}
}

/*
* 标签
*/
class FCLabel extends FCView {
	// 构造函数
	constructor() {
		super();
		super.viewType = "label";
		super.borderColor = "none";
	}
}

/*
* 文本框
*/
class FCTextBox extends FCView {
	// 构造函数
	constructor() {
		super();
		super.viewType = "textbox";
	}
}

/*
* 数值输入框
*/
class FCSpin extends FCView {
	// 构造函数
	constructor() {
		super();
		super.viewType = "spin";
	}
}

/*
* 图层
*/
class FCDiv extends FCView {
	// 构造函数
	constructor() {
		super();
		super.viewType = "div";
	}
}

/*
* 页
*/
class FCTabPage extends FCView {
	public headerButton : FCView | null = null; //页头的按钮
	// 构造函数
	constructor() {
		super();
		super.viewType = "tabpage";
		super.visible = false;
	}
}

/*
* 多页夹
*/
class FCTabView extends FCView {
	public animationSpeed : number = 20; //动画速度
	public layout : string = "top"; //布局方式
	public tabPages : Array<FCTabPage> = []; //页夹集合
	public underLineColor : string | null = null; //下划线的颜色
	public underLineSize : number = 0; //下划线的宽度
	public underPoint : FCPoint = new FCPoint(0, 0); //下划点
	public useAnimation : boolean = false; //是否使用动画
	// 构造函数
	constructor() {
		super();
		super.viewType = "tabview";
	}
}

/*
* 复选按钮
*/
class FCCheckBox extends FCView {
	public buttonSize : FCSize = new FCSize(16, 16); //按钮的大小
	public checked : boolean = false; //是否选中
	// 构造函数
	constructor() {
		super();
		super.viewType = "checkbox";
	}
}

/*
 * 多布局图层
 */
class FCLayoutDiv extends FCDiv {
	public autoWrap : boolean = false; //是否自动换行
	public layoutStyle : string = "lefttoright"; //分割方式
	// 构造函数
	constructor() {
		super();
		super.viewType = "layout";
	}
}

/*
* 分割图层
*/
class FCSplitLayoutDiv extends FCView {
	public firstView : FCView | null = null; //第一个视图
	public layoutStyle : string = "lefttoright"; //分割方式
	public oldSize : FCSize = new FCSize(0, 0); //上次的尺寸
	public splitMode : string = "absolutesize"; //分割模式 percentsize百分比或absolutesize绝对值
	public splitPercent : number = -1; //分割百分比
	public secondView : FCView | null = null; //第二个视图
	public splitter : FCView | null = null; //分割线
	// 构造函数
	constructor() {
		super();
		super.viewType = "split";
	}
}

/*
* 单选按钮
*/
class FCRadioButton extends FCView {
	public buttonSize : FCSize = new FCSize(16, 16); //按钮的大小
	public checked : boolean = false; //是否选中
	public groupName : string = "";  //组别
	// 构造函数
	constructor() {
		super();
		super.viewType = "radiobutton";
	}
}

/*
* 表格列
*/
class FCGridColumn {
	public allowSort : boolean = true; //是否允许排序
	public allowResize : boolean = false; //是否允许改变大小
	public backColor : string = "rgb(200,200,200)"; //背景色
	public borderColor : string = "rgb(150,150,150)"; //边线颜色
	public bounds : FCRect = new FCRect(0, 0, 0, 0); //区域
	public cellAlign : string = "left"; //left:居左 center:居中 right:居右
	public colName : string = ""; //名称
	public colType : string = ""; //类型 string:字符串 double:浮点型 int:整型 bool: 布尔型
	public font : string = "Default,14"; //字体
	public frozen : boolean = false; //是否冻结
	public index : number = -1; //索引
	public text : string = ""; //文字
	public textColor : string = "rgb(50,50,50)"; //文字颜色
	public shapeType : string = ""; //类型
	public sort : string = "none"; //排序模式
	public width : number = 120; //宽度
	public widthStr : string = ""; //宽度字符串
	public visible : boolean = true; //是否可见
}

/*
* 表格单元格
*/
class FCGridCell {
	public backColor : string = "rgb(255,255,255)"; //背景色
	public borderColor : string = "rgb(150,150,150)"; //边线色
	public colSpan : number = 1; //列距
	public column : FCGridColumn | null = null; //所在列
	public digit : number = -1; //保留小数的位数
	public font : string = "Default,14"; //字体
	public row : FCGridRow | null = null; //所在行
	public rowSpan : number = 1; //行距
	public textColor : string = "rgb(0,0,0)"; //前景色
	public value : string = ""; //值
	public view : FCView | null = null; //包含的视图
}

/*
* 表格行
*/
class FCGridRow {
	public cells : Array<FCGridCell> = []; //单元格
	public index : number = -1;
	public key : string = ""; //排序键值
	public selected : boolean = false; //是否选中
	public visible : boolean = true; //是否可见
}

/*
* 表格
*/
class FCGrid extends FCView {
	public columns : Array<FCGridColumn> = []; //所有的列
	public headerHeight : number = 30; //头部高度
	public rowHeight : number = 30; //行高
	public rows : Array<FCGridRow> = []; //包含的所有行
	public seletedRowColor : string = "rgb(125,125,125)"; //选中行的颜色
	public selectedRowColor : string = "rgb(125,125,125)"; //选中行的颜色
	// 构造函数
	constructor() {
		super();
		super.viewType = "grid";
		super.showHScrollBar = true;
		super.showVScrollBar = true;
	}
}

/*
* 树的列
*/
class FCTreeColumn {
	public bounds : FCRect = new FCRect(0, 0, 0, 0); //区域
	public index : number = -1; //索引
	public visible : boolean = true; //是否可见
	public width : number = 120; //宽度
}

/*
* 树的行
*/
class FCTreeRow {
	public cells : Array<FCTreeNode> = []; //单元格
	public index : number = -1; //索引
	public selected : boolean = false; //是否选中
	public visible : boolean = true; //是否可见
}

/*
* 树节点
*/
class FCTreeNode {
	public allowCollapsed : boolean = true; //是否允许折叠
	public backColor : string = "rgb(255,255,255)"; //背景色
	public checked : boolean = false; //是否选中
	public childNodes : Array<FCTreeNode> = []; //子节点
	public collapsed : boolean = false; //是否折叠
	public column : FCTreeColumn | null = null; //所有的列
	public font : string = "Default,14";//字体
	public indent : number = 0; //缩进
	public parentNode : FCTreeNode | null = null;
	public row : FCTreeRow | null = null;//包含的所有行
	public textColor : string = "rgb(0,0,0)"; //前景色
	public value : string = ""; //值	
}

/*
* 树
*/
class FCTree extends FCView {
	public checkBoxWidth : number = 25; //复选框占用的宽度
	public columns : Array<FCTreeColumn> = []; //所有的列
	public collapsedWidth : number = 25; //折叠按钮占用的宽度
	public childNodes : Array<FCTreeNode> = []; //子节点
	public headerHeight : number = 0; //头部高度
	public indent : number = 20; //缩进
	public rowHeight : number = 30; //行高
	public rows : Array<FCTreeRow> = []; //包含的所有行
	public showCheckBox : boolean = false; //是否显示复选框
	// 构造函数
	constructor() {
		super();
		super.viewType = "tree";
		super.showHScrollBar = true;
		super.showVScrollBar = true;
	}
}

/*
* 证券数据结构
*/
class SecurityData {
	public amount : number = 0.0; //成交额
	public close : number = 0.0; //收盘价
	public date : number = 0.0; //日期，为1970年到现在的秒
	public high : number = 0.0; //最高价
	public low : number = 0.0; //最低价
	public open : number = 0.0; //开盘价
	public volume : number = 0.0; //成交额
}

/*
* 基础图形
*/
class BaseShape {
	public color : string | null = null; //颜色
	public color2 : string | null = null; //颜色2
	public datas : Array<number> = []; //第一组数据
	public datas2 : Array<number> = []; //第二组数据
	public divIndex : number = 0; //所在层
	public leftOrRight : boolean = true; //依附于左轴或右轴
	public lineWidth : number = 1; //线的宽度
	public shapeType : string = "line"; //类型
	public shapeName : string = ""; //名称
	public showHideDatas : Array<number> = []; //控制显示隐藏的数据
	public style : string = ""; //样式
	public text : string = ""; //显示的文字
	public title : string = ""; //第一个标题
	public title2 : string = ""; //第二个标题
	public value : number = 0; //显示文字的值
}

/*
* 画线工具结构
*/
class FCPlot {
	public key1 : number = 0.0; //第一个键
	public key2 : number = 0.0; //第二个键
	public key3 : number = 0.0; //第三个键
	public lineColor : string = "rgb(0,0,0)"; //线的颜色
	public lineWidth : number = 1; //线的宽度
	public plotType : string = "Line"; //线的类型
	public pointColor : string = "rgba(0,0,0,120)"; //线的颜色
	public startKey1 : number = 0.0; //移动前第一个键
	public startValue1 : number = 0.0; //移动前第一个值
	public startKey2 : number = 0.0; //移动前第二个键
	public startValue2 : number = 0.0; //移动前第二个值
	public startKey3 : number = 0.0; //移动前第三个键
	public startValue3 : number = 0.0; //移动前第三个值
	public value1 : number = 0.0; //第一个值
	public value2 : number = 0.0; //第二个值
	public value3 : number = 0.0; //第三个值
}

/*
* 图表
*/
class FCChart extends FCView {
	public autoFillHScale : boolean = false; //是否填充满X轴
	public allowDragChartDiv : boolean = false; //是否允许拖拽图层
	public candleDistance : number = 0; //蜡烛线的距离
	public candleMax : number = 0; //蜡烛线的最大值
	public candleMin : number = 0; //蜡烛线的最小值
	public candleMaxRight : number = 0; //蜡烛线的右轴最大值
	public candleMinRight : number = 0; //蜡烛线的右轴最小值
	public crossTipColor : string = "rgb(50,50,50)"; //十字线标识的颜色
	public crossLineColor : string = "rgb(100,100,100)"; //十字线的颜色
	public candleDigit : number = 2; //图表层保留小数的位数
	public candleDivPercent : number = 0.5; //图表层的占比
	public candlePaddingTop : number = 30; //图表层的上边距
	public candlePaddingBottom : number = 30; //图表层的下边距
	public crossStopIndex : number = -1; //鼠标停留位置
	public cycle : string = "second"; //周期
	public data : Array<SecurityData> = []; //子节点
	public downColor : string = "rgb(15,193,118)";  //下跌颜色
	public firstVisibleIndex : number = -1; //起始可见的索引
	public gridColor : string = "rgba(255,0,0,120)"; //网格颜色
	public hScalePixel : number = 11; //蜡烛线的宽度
	public hScaleHeight : number = 30; //X轴的高度
	public hScaleTextDistance : number = 10; //X轴的文字间隔
	public hScaleFormat : string = ""; //X轴的格式化字符，例如YYYY-mm-dd HH:MM:SS
	public indMax : number = 0; //指标层的最大值
	public indMin : number = 0; //指标的最小值
	public indMax2 : number = 0; //指标层2的最大值
	public indMin2 : number = 0; //指标层2的最小值
	public indMaxRight : number = 0; //指标层的右轴最大值
	public indMinRight : number = 0; //指标层的右轴最小值
	public indMax2Right : number = 0; //指标层2的右轴最大值
	public indMin2Right : number = 0; //指标层2的右轴最小值
	public indDigit : number = 2; //指标层保留小数的位数
	public indDigit2 : number = 2; //指标层2保留小数的位数
	public indDivPercent : number = 0.3; //指标层的占比
	public indDivPercent2 : number = 0.0; //指标层2的占比
	public indPaddingTop : number = 20; //指标层的上边距
	public indPaddingBottom : number = 20; //指标层的下边距
	public indPaddingTop2 : number = 20; //指标层2的上边距
	public indPaddingBottom2 : number = 20; //指标层2的下边距
	public indicatorColors : Array<string> = []; //扩展图形
	public leftVScaleWidth : number = 80; //左轴宽度
	public lastVisibleIndex : number = -1; //结束可见的索引
	public lastRecordIsVisible : boolean = true; //最后记录是否可见
	public lastVisibleKey : number = 0; //最后可见的主键
	public lastValidIndex : number = -1; //最后有效数据索引
	public lineWidthChart : number = 1;
	public mainIndicator : string = ""; //主图指标
	public magnitude : number = 1; //成交量的比例
	public plots : Array<FCPlot> = []; //画线
	public plotPointSizeChart : number = 5;  //画线的选中点大小
	public rightVScaleWidth : number = 0; //右轴宽度
	public rightSpace : number = 0; //右侧空间
	public scaleColor : string = "rgb(255,0,0)"; //刻度的颜色
	public showIndicator : string = ""; //显示指标
	public showCrossLine : boolean = false; //是否显示十字线
	public selectPlotPoint : number = -1; //选中画线的点
	public startMovePlot : boolean = false; //选中画线
	public selectShape : string = ""; //选中的图形
	public selectShapeEx : string = ""; //选中的图形信息
	public shapes : Array<BaseShape> = []; //扩展图形
	public sPlot : FCPlot | null = null; //选中的线条
	public touchPosition : FCPoint = new FCPoint(0, 0); //鼠标坐标
	public volMax : number = 0; //成交量层的最大值
	public volMin : number = 0; //成交量层的最小值
	public volMaxRight : number = 0; //成交量层的右轴最大值
	public volMinRight : number = 0; //成交量层的右轴最小值
	public volDigit : number = 0; //成交量层保留小数的位数
	public volDivPercent : number = 0.2; //成交量层的占比
	public volPaddingTop : number = 20; //成交量层的上边距
	public volPaddingBottom : number = 0; //成交量层的下边距
	public vScaleDistance : number = 35; //纵轴的间隔
	public vScaleType : string = "standard"; //纵轴的类型 log10代表指数坐标
	public upColor : string = "rgb(219,68,83)";  //上涨颜色
	public kChart : number = 0.0;
	public bChart : number = 0.0;
	public oXChart : number = 0.0;
	public oYChart : number = 0.0;
	public rChart : number = 0.0;
	public gridStepChart : number = 0.0; //网格计算临时变量
	public gridDigitChart : number = 0.0; //网格计算临时变量
	//拖动滚动的缓存
	public firstIndexCacheChart : number = -1;
	public firstTouchIndexCacheChart : number = -1;
	public firstTouchPointCacheChart : FCPoint = new FCPoint(0, 0);
	public lastIndexCacheChart : number = -1;
	public secondTouchIndexCacheChart : number = -1;
	public secondTouchPointCacheChart : FCPoint = new FCPoint(0, 0);
	public firstPaddingTop : number = 0.0;
	public firtstPaddingBottom : number = 0.0;
	public touchDownPointChart : FCPoint = new FCPoint(0, 0);
	public addingPlotChart : string = "";
	public x4Chart : number = 0.0;
	public y4Chart : number = 0.0;
	public nHighChart : number = 0.0;
	public nLowChart : number = 0.0;
	public xChart : number = 0.0;
	public yChart : number = 0.0;
	public wChart : number = 0.0;
	public hChart : number = 0.0;
	public upSubValue : number = 0.0;
	public downSubValue : number = 0.0;
	public allema12 : Array<number> = [];
	public allema26 : Array<number> = [];
	public alldifarr : Array<number> = [];
	public alldeaarr : Array<number> = [];
	public allmacdarr : Array<number> = [];
	public bollUp : Array<number> = [];
	public bollDown : Array<number> = [];
	public bollMid : Array<number> = [];
	public bias1 : Array<number> = [];
	public bias2 : Array<number> = [];
	public bias3 : Array<number> = [];
	public kdjK : Array<number> = [];
	public kdjD : Array<number> = [];
	public kdjJ : Array<number> = [];
	public rsi1 : Array<number> = [];
	public rsi2 : Array<number> = [];
	public rsi3 : Array<number> = [];
	public roc : Array<number> = [];
	public rocMa : Array<number> = [];
	public wr1 : Array<number> = [];
	public wr2 : Array<number> = [];
	public cci : Array<number> = [];
	public bbi : Array<number> = [];
	public trix : Array<number> = [];
	public trixMa : Array<number> = [];
	public dma1 : Array<number> = [];
	public dma2 : Array<number> = [];
	public ma5 : Array<number> = [];
	public ma10 : Array<number> = [];
	public ma20 : Array<number> = [];
	public ma30 : Array<number> = [];
	public ma120 : Array<number> = [];
	public ma250 : Array<number> = [];
	public closeArr : Array<number> = [];
	// 构造函数
	constructor() {
		super();
		super.viewType = "chart";
		super.showHScrollBar = true;
		super.showVScrollBar = true;
		this.indicatorColors.push("rgb(100,100,100)");
		this.indicatorColors.push("rgb(206,147,27)");
		this.indicatorColors.push("rgb(150,0,150)");
		this.indicatorColors.push("rgb(255,0,0)");
		this.indicatorColors.push("rgb(0,150,150)");
		this.indicatorColors.push("rgb(0,150,0)");
		this.indicatorColors.push("rgb(59,174,218)");
		this.indicatorColors.push("rgb(50,50,50)");
	}
}

/*
* 月层
*/
class MonthDiv {
	public aDirection : number = 0; //动画的方向
	public aTick : number = 0; //动画当前帧数
	public aTotalTick : number = 40; //动画总帧数
	public month : number = 0; //月份
	public monthButtons : Array<MonthButton> = []; //月的按钮
	public monthButtonsAm : Array<MonthButton> = []; //动画日期的集合
	public year : number = 0; //年份
}

/*
* 年层
*/
class YearDiv {
	public aDirection : number = 0; //动画的方向
	public aTick : number = 0; //动画当前帧数
	public aTotalTick : number = 40; //动画总帧数
	public startYear : number = 0; //开始年份
	public yearButtons : Array<YearButton> = []; //年的按钮
	public yearButtonsAm : Array<YearButton> = []; //动画日期的集合
}

/*
* 头部层
*/
class HeadDiv {
	public arrowColor : string = "rgb(150,150,150)"; //箭头颜色
	public backColor : string = "rgb(255,255,255)"; //箭头颜色
	public bounds : FCRect = new FCRect(0, 0, 0, 0); //显示区域
	public textColor : string = "rgb(0,0,0)"; //文字颜色
	public titleFont : string = "Default,20"; //标题字体
	public weekFont : string = "Default,14"; //星期字体
}

/*
* 时间层
*/
class TimeDiv {
	public bounds : FCRect = new FCRect(0, 0, 0, 0); //显示区域
}

/*
* 年的结构
*/
class CYear {
	public months : Map<number, CMonth> = new Map<number, CMonth>(); //月的集合
	public year : number = 0; //年
}

/*
* 月的结构
*/
class CMonth {
	public days : Map<number, CDay> = new Map<number, CDay>(); //日的集合
	public month : number = 0; //月
	public year : number = 0; //年
}

/*
* 日的结构
*/
class CDay {
	public day : number = 0; //日
	public month : number = 0; //月
	public year : number = 0; //年
}

/*
* 日历
*/
class FCCalendar extends FCView {
	public dayDiv : DayDiv | null = new DayDiv(); //日层
	public headDiv : HeadDiv | null = new HeadDiv(); //头部层
	public mode : string = "day"; //模式
	public monthDiv : MonthDiv | null = new MonthDiv(); //月层
	public selectedDay : CDay | null = new CDay(); //选中日
	public timeDiv : TimeDiv | null = new TimeDiv(); //时间层
	public useAnimation : boolean = false; //是否使用动画
	public yearDiv : YearDiv | null = new YearDiv(); //年层
	public years : Map<number, CYear> = new Map<number, CYear>(); //日历
	// 构造函数
	constructor() {
		super();
		super.viewType = "calendar";
	}
}

/*
* 日的按钮
*/
class DayButton {
	public backColor : string | null = null; //背景颜色
	public borderColor : string = "rgb(150,150,150)"; //文字颜色
	public bounds : FCRect = new FCRect(0, 0, 0, 0); //显示区域
	public day : CDay | null = null; //日期
	public font : string = "Default,16"; //字体
	public inThisMonth : boolean = false; //是否在本月
	public selected : boolean = false; //是否被选中
	public textColor : string = "rgb(0,0,0)"; //文字颜色
	public textColor2 : string = "rgb(50,50,50)"; //第二个文字颜色
	public visible : boolean = true; //是否可见	
}

/*
* 月的按钮
*/
class MonthButton {
	public bounds : FCRect = new FCRect(0, 0, 0, 0); //显示区域
	public backColor : string | null = null; //背景颜色
	public borderColor : string = "rgb(150,150,150)"; //文字颜色
	public font : string = "Default,16"; //字体
	public month : number = 0; //月
	public textColor : string = "rgb(0,0,0)"; //文字颜色
	public visible : boolean = true; //是否可见
	public year : number = 0; //年
}

/*
* 年的按钮
*/
class YearButton {
	public backColor : string | null = null; //背景颜色
	public borderColor : string = "rgb(150,150,150)"; //文字颜色
	public bounds : FCRect = new FCRect(0, 0, 0, 0); //显示区域
	public font : string = "Default,16"; //字体
	public textColor : string = "rgb(0,0,0)"; //文字颜色
	public visible : boolean = true; //是否可见
	public year : number = 0; //年
}

/*
* 日期层
*/
class DayDiv {
	public aClickRowFrom : number = 0; //点击时的上月的行
	public aClickRowTo : number = 0; //点击时的当月的行
	public aDirection : number = 0; //动画的方向
	public aTick : number = 0; //动画当前帧数
	public aTotalTick : number = 40; //动画总帧数
	public dayButtons : Array<DayButton> = []; //日期的集合
	public dayButtonsAm : Array<DayButton> = []; //动画日期的集合
}

/*
* 菜单
*/
class FCMenu extends FCLayoutDiv {
	public autoSize : boolean = true; //是否自动适应尺寸
	public comboBox : FCComboBox | null = null; //所在的下拉菜单
	public items : Array<FCMenuItem> = []; //菜单项
	public popup : boolean = true; //是否弹出
	// 构造函数
	constructor() {
		super();
		super.viewType = "menu";
		super.size = new FCSize(100, 100);
		super.showHScrollBar = true;
		super.showVScrollBar = true;
		super.visible = false;
		super.layoutStyle = "toptobottom";
		super.autoWrap = false;
		super.maximumSize = new FCSize(100, 300);
		super.allowPreviewsEvent = true;
	}
}

/*
* 菜单项
*/
class FCMenuItem extends FCView {
	public checked : boolean = false; //是否选中
	public dropDownMenu : FCMenu | null = null; //下拉菜单
	public items : Array<FCMenuItem> = []; //菜单项
	public parentMenu : FCMenu | null = null; //所在菜单
	public parentItem : FCMenuItem | null = null; //父菜单项
	public value : string = ""; //值
	// 构造函数
	constructor() {
		super();
		super.viewType = "menuitem";
		super.hoveredColor = "rgb(150,150,150)";
		super.pushedColor = "rgb(200,200,200)";
		super.size = new FCSize(100, 25);
	}
}

/*
* 下拉选择
*/
class FCComboBox extends FCView {
	public dropDownMenu : FCMenu | null = null; //下拉菜单 
	public selectedIndex : number = -1; //选中索引
	// 构造函数
	constructor() {
		super();
		super.viewType = "combobox";
	}
}

/*
* 添加顶层视图
* view 视图
* paint 绘图对象
*/
function addView(view : FCView, paint : FCPaint) {
	view.paint = paint;
	paint.views.push(view);
}

/*
* 添加到父视图
* view 视图
* parent 父视图
*/
function addViewToParent(view : FCView, parent : FCView) {
	view.paint = parent.paint;
	parent.views.push(view);
	view.parent = parent;
}

/*
* 清除视图
* paint 绘图对象
*/
function clearViews(paint: FCPaint) {
  paint.views = [];
}

/*
* 移除顶层视图
* view 视图
* paint 绘图对象
*/
function removeView(view : FCView, paint : FCPaint) {
	if (paint.views) {
		for (let i = 0; i < paint.views.length; i++) {
			if (paint.views[i] == view) {
				paint.views.splice(i, 1);
				break;
			}
		}
	}
}

/*
* 从父视图中移除
* view 视图
* parent 父视图
*/
function removeViewFromParent(view : FCView, parent : FCView) {
	if (parent.views) {
		for (let i = 0; i < parent.views.length; i++) {
			if (parent.views[i] == view) {
				parent.views.splice(i, 1);
				break;
			}
		}
	}
}

/*
* 获取绝对位置X
* view:视图
*/
function clientX(view : FCView | null) : number {
	if (view != null) {
		let cLeft = view.location.x;
		if (view.parent != null) {
			if (view.parent!.displayOffset && view.parent!.scrollH != 0) {
				return cLeft + clientX(view.parent!) - view.parent!.scrollH;
			} else {
				return cLeft + clientX(view.parent!);
			}
		} else {
			return cLeft;
		}
	} else {
		return 0;
	}
}

/*
* 获取绝对位置Y
* view:视图
*/
function clientY(view : FCView | null) : number {
	if (view != null) {
		let cTop = view.location.y;
		if (view.parent != null) {
			if (view.parent!.displayOffset && view.parent!.scrollV != 0) {
				return cTop + clientY(view.parent!) - view.parent!.scrollV;;
			} else {
				return cTop + clientY(view.parent!);
			}
		} else {
			return cTop;
		}
	} else {
		return 0;
	}
}

/*
* 是否包含坐标
* view:视图
* mp:坐标
*/
function containsPoint(view : FCView, mp : FCPoint) : boolean {
	if(isViewEnabled(view)){
		let clx = clientX(view);
		let cly = clientY(view);
		let size = view.size;
		let cp = new FCPoint(mp.x - clx, mp.y - cly);
		if (cp.x >= 0 && cp.x <= size.cx &&
			cp.y >= 0 && cp.y <= size.cy) {
			return true;
		} else {
			return false;
		}
	}else{
		return false;
	}
}

/*
* 查找有预处理事件的父视图
* view:视图
*/
function findPreviewsEventParent(view : FCView) : FCView | null {
	if (!view.allowPreviewsEvent && view.parent != null) {
		if (view.parent!.allowPreviewsEvent) {
			return view.parent;
		} else {
			return findPreviewsEventParent(view.parent!);
		}
	} else {
		return null;
	}
}

/*
* 根据名称查找视图
* name:名称
* views:视图集合
*/
function findViewByName(name : String, views : Array<FCView>) : FCView | null {
	let size = views.length;
	for (let i = 0; i < size; i++) {
		let view = views[i];
		if (view.viewName == name) {
			return view;
		} else {
			if (view.views) {
				let subView = findViewByName(name, view.views);
				if (subView) {
					return subView;
				}
			}
		}
	}
	return null;
}

/*
* 根据坐标查找视图
* mp:坐标
* views:视图集合
*/
function findView(mp : FCPoint, views : Array<FCView>) : FCView | null {
	let size = views.length;
	for (let i = size - 1; i >= 0; i--) {
		let view = views[i];
		if (view.visible && view.topMost) {
			let hasPoint = false;
			if (view.paint!.onContainsPoint != null) {
				hasPoint = view.paint!.onContainsPoint!(view, mp);
			} else {
				hasPoint = containsPoint(view, mp);
			}
			if (hasPoint) {
				if (view.vScrollIsVisible) {
					let clx = clientX(view);
					if (mp.x >= clx + view.size.cx - view.scrollSize) {
						return view;
					}
				}
				if (view.hScrollIsVisible) {
					let cly = clientY(view);
					if (mp.y >= cly + view.size.cy - view.scrollSize) {
						return view;
					}
				}
				let subView = findView(mp, view.views);
				if (subView != null) {
					return subView;
				}
				return view;
			}
		}
	}
	for (let i = size - 1; i >= 0; i--) {
		let view = views[i];
		if (view.visible && !view.topMost) {
			let hasPoint = false;
			if (view.paint!.onContainsPoint != null) {
				hasPoint = view.paint!.onContainsPoint!(view, mp);
			} else {
				hasPoint = containsPoint(view, mp);
			}
			if (hasPoint) {
				if (view.vScrollIsVisible) {
					let clx = clientX(view);
					if (mp.x >= clx + view.size.cx - view.scrollSize) {
						return view;
					}
				}
				if (view.hScrollIsVisible) {
					let cly = clientY(view);
					if (mp.y >= cly + view.size.cy - view.scrollSize) {
						return view;
					}
				}
				let subView = findView(mp, view.views);
				if (subView != null) {
					return subView;
				}
				return view;
			}
		}
	}
	return null;
}

/*
* 是否重绘时可见
* view:视图
*/
function isPaintVisible(view : FCView) : boolean {
	if (view.visible) {
		if (view.parent != null) {
			if (view.parent!.visible) {
				return isPaintVisible(view.parent!);
			} else {
				return false;
			}
		} else {
			return true;
		}
	} else {
		return false;
	}
}

/*
* 是否重绘时可见
* view:视图
*/
function isViewEnabled(view : FCView) : boolean {
	if (view.enabled) {
		if (view.parent != null) {
			if (view.parent!.enabled) {
				return isViewEnabled(view.parent!);
			} else {
				return false;
			}
		} else {
			return true;
		}
	} else {
		return false;
	}
}

/*
* 获取区域的交集
*/
function getIntersectRect(lpDestRect : FCRect, lpSrc1Rect : FCRect, lpSrc2Rect : FCRect) : number {
	lpDestRect.left = Math.max(lpSrc1Rect.left, lpSrc2Rect.left);
	lpDestRect.right = Math.min(lpSrc1Rect.right, lpSrc2Rect.right);
	lpDestRect.top = Math.max(lpSrc1Rect.top, lpSrc2Rect.top);
	lpDestRect.bottom = Math.min(lpSrc1Rect.bottom, lpSrc2Rect.bottom);
	if (lpDestRect.right > lpDestRect.left && lpDestRect.bottom > lpDestRect.top) {
		return 1;
	}
	else {
		lpDestRect.left = 0;
		lpDestRect.right = 0;
		lpDestRect.top = 0;
		lpDestRect.bottom = 0;
		return 0;
	}
}

/*
* 重绘视图
* views:视图集合
* paint:绘图对象
* rect:区域
*/
function renderViews(views : Array<FCView>, paint : FCPaint, rect : FCRect | null) {
	let viewsSize = views.length;
	for (let i = 0; i < viewsSize; i++) {
		let view = views[i];
		if (rect == null) {
			let subViewsSize = view.views.length;
			if (subViewsSize > 0) {
				renderViews(view.views, paint, null);
			}
			view.clipRect = new FCRect(0, 0, 0, 0);
			continue;
		}
		if (!view.topMost && isPaintVisible(view)) {
			let clx = clientX(view);
			let cly = clientY(view);
			let drawRect = new FCRect(0, 0, view.size.cx, view.size.cy);
			let clipRect = new FCRect(clx, cly, clx + view.size.cx, cly + view.size.cy);
			let destRect = new FCRect(0, 0, 0, 0);
			if (getIntersectRect(destRect, rect, clipRect) > 0) {
				paint.save();
				paint.setOffset(0, 0);
				paint.setClip(destRect.left, destRect.top, destRect.right, destRect.bottom);
				view.clipRect = destRect;
				paint.setOffset(clx, cly);
				if (paint.onPaint != null) {
					paint.onPaint!(view, paint, drawRect);
				} else {
					onPaintDefault(view, paint, drawRect);
				}
				let subViewsSize = view.views.length;
				if (subViewsSize > 0) {
					renderViews(view.views, paint, destRect);
				}
				paint.setOffset(clx, cly);
				if (paint.onPaintBorder != null) {
					paint.onPaintBorder!(view, paint, drawRect);
				} else {
					onPaintBorderDefault(view, paint, drawRect);
				}
				paint.restore();
			} else {
				let subViewsSize = view.views.length;
				if (subViewsSize > 0) {
					renderViews(view.views, paint, null);
				}
				view.clipRect = new FCRect(0, 0, 0, 0);
			}
		}
	}
	for (let i = 0; i < viewsSize; i++) {
		let view = views[i];
		if (rect == null) {
			continue;
		}
		if (view.topMost && isPaintVisible(view)) {
			let clx = clientX(view);
			let cly = clientY(view);
			let drawRect = new FCRect(0, 0, view.size.cx, view.size.cy);
			let clipRect = new FCRect(clx, cly, clx + view.size.cx, cly + view.size.cy);
			let destRect = new FCRect(0, 0, 0, 0);
			if (getIntersectRect(destRect, rect, clipRect) > 0) {
				paint.save();
				paint.setOffset(0, 0);
				view.clipRect = destRect;
				paint.setClip(destRect.left, destRect.top, destRect.right, destRect.bottom);
				paint.setOffset(clx, cly);
				if (paint.onPaint != null) {
					paint.onPaint!(view, paint, drawRect);
				} else {
					onPaintDefault(view, paint, drawRect);
				}
				let subViewsSize = view.views.length;
				if (subViewsSize > 0) {
					renderViews(view.views, paint, destRect);
				}
				paint.setOffset(clx, cly);
				if (paint.onPaintBorder != null) {
					paint.onPaintBorder!(view, paint, drawRect);
				} else {
					onPaintBorderDefault(view, paint, drawRect);
				}
				paint.restore();
			}
			else {
				let subViewsSize = view.views.length;
				if (subViewsSize > 0) {
					renderViews(view.views, paint, null);
				}
				view.clipRect = new FCRect(0, 0, 0, 0);
			}
		}
	}
}

/*
* 全局刷新方法
* paint:绘图对象
*/
function invalidate(paint : FCPaint) {
	let drawViews = paint.views;
	if (paint.onInvalidate != null) {
		paint.onInvalidate!(paint);
	} else {
		paint.beginPaint(null);
		let drawRect = new FCRect(0, 0, (paint.size.cx / paint.ratio / paint.scaleFactorX), (paint.size.cy / paint.ratio / paint.scaleFactorY));
		if (paint!.onRenderViews != null) {
			paint!.onRenderViews!(drawViews, paint, drawRect);
		} else {
			renderViews(drawViews, paint, drawRect);
		}
		paint.endPaint();
	}
}

/*
* 刷新视图方法
* view:视图
*/
function invalidateView(view : FCView) {
	let paint = view.paint;
	invalidate(paint!);
}

/*
* 更新悬浮状态
* views:视图集合
*/
function updateViewDefault(views : Array<FCView>) {
	for (let i = 0; i < views.length; i++) {
		let view = views[i];
		if (view.paint != null) {
			if (view.exAttributes.has("leftstr")) {
				var pWidth = view.paint!.size.cx / view.paint!.ratio / view.paint!.scaleFactorX;
				if (view.parent != null) {
					pWidth = view.parent!.size.cx;
				}
				let newStr = view.exAttributes.get("leftstr") as string;
				newStr = newStr.replace("%", "");
				view.location.x = strToNumber(newStr) * pWidth / 100;
			}
			if (view.exAttributes.has("topstr")) {
				var pHeight = view.paint!.size.cy / view.paint!.ratio / view.paint!.scaleFactorY;
				if (view.parent != null) {
					pHeight = view.parent!.size.cy;
				}
				let newStr = view.exAttributes.get("topstr") as string;
				newStr = newStr.replace("%", "");
				view.location.y = strToNumber(newStr) * pHeight / 100;
			}
			if (view.exAttributes.has("widthstr")) {
				var pWidth = view.paint!.size.cx / view.paint!.ratio / view.paint!.scaleFactorX;
				if (view.parent != null) {
					pWidth = view.parent!.size.cx;
				}
				let newStr = view.exAttributes.get("widthstr") as string;
				newStr = newStr.replace("%", "");
				view.size.cx = strToNumber(newStr) * pWidth / 100;
			}
			if (view.exAttributes.has("heightstr")) {
				var pHeight = view.paint!.size.cy / view.paint!.ratio / view.paint!.scaleFactorY;
				if (view.parent != null) {
					pHeight = view.parent!.size.cy;
				}
				let newStr = view.exAttributes.get("heightstr") as string;
				newStr = newStr.replace("%", "");
				view.size.cy = strToNumber(newStr) * pHeight / 100;
			}
			if (view.parent != null && view.parent!.viewType != "split") {
				let margin = view.margin;
			let padding = view.parent.padding;
			if (view.dock == "fill") {
				view.location = new FCPoint(margin.left + padding.left, margin.top + padding.top);
				let vcx = view.parent.size.cx - margin.left - padding.left - margin.right - padding.right;
				if (vcx < 0){
					vcx = 0;
				}
				let vcy = view.parent.size.cy - margin.top - padding.top - margin.bottom - padding.bottom;
				if (vcy < 0){
					vcy = 0;
				}
				view.size = new FCSize(vcx, vcy);
			} else if (view.dock == "left") {
				view.location = new FCPoint(margin.left + padding.left, margin.top + padding.top);
				let vcy = view.parent.size.cy - margin.top - padding.top - margin.bottom - padding.bottom;
				if (vcy < 0){
					vcy = 0;
				}
				view.size = new FCSize(view.size.cx, vcy);
			} else if (view.dock == "top") {
				view.location = new FCPoint(margin.left + padding.left, margin.top + padding.top);
				let vcx = view.parent.size.cx - margin.left - padding.left - margin.right - padding.right;
				if (vcx < 0){
					vcx = 0;
				}
				view.size = new FCSize(vcx, view.size.cy);
			} else if (view.dock == "right") {
				view.location = new FCPoint(view.parent.size.cx - view.size.cx - padding.right - margin.right, margin.top + padding.top);
				let vcy = view.parent.size.cy - margin.top - padding.top - margin.bottom - padding.bottom;
				if (vcy < 0){
					vcy = 0;
				}
				view.size = new FCSize(view.size.cx, vcy);
			} else if (view.dock == "bottom") {
				view.location = new FCPoint(margin.left + padding.left, view.parent.size.cy - view.size.cy - margin.bottom - padding.bottom);
				let vcx = view.parent.size.cx - margin.left - padding.left - margin.right - padding.right;
				if (vcx < 0){
					vcx = 0;
				}
				view.size = new FCSize(vcx, view.size.cy);
			}
			if (view.align == "center") {
				view.location = new FCPoint((view.parent.size.cx - view.size.cx) / 2, view.location.y);
			}else if(view.align == "right"){
				view.location = new FCPoint(view.parent.size.cx - view.size.cx - padding.right - margin.right, view.location.y);
			}
			if (view.verticalAlign == "middle") {
				view.location = new FCPoint(view.location.x, (view.parent.size.cy - view.size.cy) / 2);
			}else if(view.verticalAlign == 'bottom'){
				view.location = new FCPoint(view.location.x, view.parent.size.cy - view.size.cy - padding.bottom - margin.bottom);
			}
			}
			else if (view.parent == null) {
				if (view.dock == "fill") {
					let paint = view.paint;
					view.size = new FCSize((paint!.size.cx / paint!.ratio / paint!.scaleFactorX), (paint!.size.cy / paint!.ratio / paint!.scaleFactorY));
				}
			}
			if (view.viewType == "split") {
				resetSplitLayoutDiv((view as any) as FCSplitLayoutDiv);
			} else if (view.viewType == "tabview") {
				updateTabLayout((view as any) as FCTabView);
			} else if (view.viewType == "layout") {
				resetLayoutDiv((view as any) as FCLayoutDiv);
			} else if (view.viewType == "calendar") {
				updateCalendar((view as any) as FCCalendar);
			} else if (view.viewType == "chart") {
				let chart = (view as any) as FCChart;
				resetChartVisibleRecord(chart);
				checkChartLastVisibleIndex(chart);
				if (chart.paint!.onCalculateChartMaxMin != null) {
					chart.paint!.onCalculateChartMaxMin!(chart);
				} else {
					calculateChartMaxMin(chart);
				}
			}
			updateViewDefault(view.views);
		}
	}
}

/*
* 视图尺寸改变
*/
function windowResize(rect : FCRect, resizePoint : number, nowPoint : FCPoint, startTouchPoint : FCPoint) {
	if (resizePoint == 0) {
		rect.left = rect.left + nowPoint.x - startTouchPoint.x;
		rect.top = rect.top + nowPoint.y - startTouchPoint.y;
	}
	else if (resizePoint == 1) {
		rect.left = rect.left + nowPoint.x - startTouchPoint.x;
		rect.bottom = rect.bottom + nowPoint.y - startTouchPoint.y;
	}
	else if (resizePoint == 2) {
		rect.right = rect.right + nowPoint.x - startTouchPoint.x;
		rect.top = rect.top + nowPoint.y - startTouchPoint.y;
	}
	else if (resizePoint == 3) {
		rect.right = rect.right + nowPoint.x - startTouchPoint.x;
		rect.bottom = rect.bottom + nowPoint.y - startTouchPoint.y;
	}
	else if (resizePoint == 4) {
		rect.left = rect.left + nowPoint.x - startTouchPoint.x;
	}
	else if (resizePoint == 5) {
		rect.top = rect.top + nowPoint.y - startTouchPoint.y;
	}
	else if (resizePoint == 6) {
		rect.right = rect.right + nowPoint.x - startTouchPoint.x;
	}
	else if (resizePoint == 7) {
		rect.bottom = rect.bottom + nowPoint.y - startTouchPoint.y;
	}
}

/*
* 获取调整尺寸的点
*/
function getResizeState(view : FCView, mp : FCPoint) : number {
	let bWidth = 5;
	let width = view.size.cx, height = view.size.cy;
	if (mp.x >= 0 && mp.x <= bWidth * 2 && mp.y >= 0 && mp.y <= bWidth * 2) {
		return 0;
	} else if (mp.x >= 0 && mp.x <= bWidth * 2 && mp.y >= height - bWidth * 2 && mp.y <= height) {
		return 1;
	} else if (mp.x >= width - bWidth * 2 && mp.x <= width && mp.y >= 0 && mp.y <= bWidth * 2) {
		return 2;
	} else if (mp.x >= width - bWidth * 2 && mp.x <= width && mp.y >= height - bWidth * 2 && mp.y <= height) {
		return 3;
	} else if (mp.x >= 0 && mp.x <= bWidth && mp.y >= 0 && mp.y <= height) {
		return 4;
	} else if (mp.x >= 0 && mp.x <= width && mp.y >= 0 && mp.y <= bWidth) {
		return 5;
	} else if (mp.x >= width - bWidth && mp.x <= width && mp.y >= 0 && mp.y <= height) {
		return 6;
	} else if (mp.x >= 0 && mp.x <= width && mp.y >= height - bWidth && mp.y <= height) {
		return 7;
	} else {
		return -1;
	}
}

/*
* 重绘复选按钮
* checkBox:视图
* paint:绘图对象
* clipRect:裁剪区域
*/
function drawCheckBox(checkBox : FCCheckBox, paint : FCPaint, clipRect : FCRect) {
	let width = checkBox.size.cx, height = checkBox.size.cy;
	if (checkBox.textColor != "none") {
		let eRight = checkBox.buttonSize.cx + 10;
		let eRect = new FCRect(1, (height - checkBox.buttonSize.cy) / 2, checkBox.buttonSize.cx + 1, (height + checkBox.buttonSize.cy) / 2);
		if (checkBox.text.length == 0) {
			eRect = new FCRect((width - checkBox.buttonSize.cx) / 2, (height - checkBox.buttonSize.cy) / 2, (width + checkBox.buttonSize.cx) / 2, (height + checkBox.buttonSize.cy) / 2);
		}
		paint.drawRect(checkBox.textColor!, 1, null, eRect.left, eRect.top, eRect.right, eRect.bottom);
		if (checkBox.checked) {
			eRect.left += 2;
			eRect.top += 2;
			eRect.right -= 2;
			eRect.bottom -= 2;
			paint.beginPath();
			paint.addLine(eRect.left, eRect.top + 8, eRect.left + 6, eRect.bottom);
			paint.addLine(eRect.left + 6, eRect.bottom, eRect.right - 1, eRect.top);
			paint.drawPath(checkBox.textColor, 1, []);
			paint.closePath();
		}
		if (checkBox.text.length > 0) {
			let tSize = paint.textSize(checkBox.text, checkBox.font);
			paint.drawText(checkBox.text, checkBox.textColor, checkBox.font, eRight, height / 2 - tSize.cy / 2);
		}
	}
}

/*
* 重绘单选按钮
* radioButton:视图
* paint:绘图对象
* clipRect:裁剪区域
*/
function drawRadioButton(radioButton : FCRadioButton, paint : FCPaint, clipRect : FCRect) {
	let width = radioButton.size.cx, height = radioButton.size.cy;
	if (radioButton.textColor != null && radioButton.textColor != "none") {
		let eRight = radioButton.buttonSize.cx + 10;
		let eRect = new FCRect(1, (height - radioButton.buttonSize.cy) / 2, radioButton.buttonSize.cx + 1, (height + radioButton.buttonSize.cy) / 2);
		paint.drawEllipse(radioButton.textColor, 1, null, eRect.left, eRect.top, eRect.right, eRect.bottom);
		if (radioButton.checked) {
			eRect.left += 2;
			eRect.top += 2;
			eRect.right -= 2;
			eRect.bottom -= 2;
			paint.fillEllipse(radioButton.textColor, eRect.left, eRect.top, eRect.right, eRect.bottom);
		}
		let tSize = paint.textSize(radioButton.text, radioButton.font);
		paint.drawText(radioButton.text, radioButton.textColor, radioButton.font, eRight, height / 2 - tSize.cy / 2);
	}
}

/*
* 重绘按钮
* button:视图 
* paint:绘图对象
* clipRect:裁剪区域
*/
function drawButton(button : FCView, paint : FCPaint, clipRect : FCRect) {
	if (button == paint.touchDownView) {
		if (button.pushedColor != null && button.pushedColor != "none") {
			paint.fillRoundRect(button.pushedColor, 0, 0, button.size.cx, button.size.cy, button.cornerRadius);
		} else {
			if (button.backColor != null && button.backColor != "none") {
				paint.fillRoundRect(button.backColor, 0, 0, button.size.cx, button.size.cy, button.cornerRadius);
			}
		}
	} else if (button == paint.touchMoveView) {
		if (button.hoveredColor != null && button.hoveredColor != "none") {
			paint.fillRoundRect(button.hoveredColor!, 0, 0, button.size.cx, button.size.cy, button.cornerRadius);
		} else {
			if (button.backColor != null && button.backColor != "none") {
				paint.fillRoundRect(button.backColor, 0, 0, button.size.cx, button.size.cy, button.cornerRadius);
			}
		}
	}
	else if (button.backColor != null && button.backColor != "none") {
		paint.fillRoundRect(button.backColor, 0, 0, button.size.cx, button.size.cy, button.cornerRadius);
	}
	if (button.textColor != null && button.textColor != "none" && button.text != null) {
		let tSize = paint.textSize(button.text, button.font);
		paint.drawText(button.text, button.textColor, button.font, (button.size.cx - tSize.cx) / 2, button.size.cy / 2 - tSize.cy / 2);
	}
	if (button.borderColor != null && button.borderColor != "none") {
		paint.drawRoundRect(button.borderColor, button.borderWidth, null, 0, 0, button.size.cx, button.size.cy, button.cornerRadius);
	}
}

/*
* 点击复选按钮
* checkBox:视图
* mp:坐标
*/
function clickCheckBox(checkBox : FCCheckBox, mp : FCPoint) {
	checkBox.checked = !checkBox.checked;
}

/*
* 点击单选按钮
* radioButton:视图
* mp: 坐标
*/
function clickRadioButton(radioButton : FCRadioButton, mp : FCPoint) {
	if (radioButton.parent != null) {
		for (let i = 0; i < radioButton.parent!.views.length; i++) {
			let iView = radioButton.parent!.views[i];
			if (iView.viewType == "radiobutton") {
				let rView = iView as FCRadioButton;
				if (rView != radioButton &&
					rView.groupName == radioButton.groupName) {
					rView.checked = false;
				}
			}
		}
	}
	radioButton.checked = true;
}

/*
* 获取月的日数
* year:年
* month:月
*/
function getDaysInMonth(year : number, month : number) : number {
	switch (month) {
		case 1:
		case 3:
		case 5:
		case 7:
		case 8:
		case 10:
		case 12:
			return 31;
		case 4:
		case 6:
		case 9:
		case 11:
			return 30;
		case 2:
			if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
				return 29;
			else
				return 28;
	}
	return 0;
}

/*
* 根据字符获取月份
* month:月
*/
function getMonthStr(month : number) : string {
	switch (month) {
		case 1:
			return "一月";
		case 2:
			return "二月";
		case 3:
			return "三月";
		case 4:
			return "四月";
		case 5:
			return "五月";
		case 6:
			return "六月";
		case 7:
			return "七月";
		case 8:
			return "八月";
		case 9:
			return "九月";
		case 10:
			return "十月";
		case 11:
			return "十一月";
		case 12:
			return "十二月";
		default:
			return "";
	}
}

/*
* 获取年
* years:年的集合
* year:年
*/
function getYear(calendar : FCCalendar, year : number) : CYear {
	let cy : CYear | null = null;
	if (!calendar.years.has(year)) {
		cy = new CYear();
		cy.year = year;
		calendar.years.set(year, cy);
		for (let i = 1; i <= 12; i++) {
			let cMonth = new CMonth();
			cMonth.year = year;
			cMonth.month = i;
			cy!.months.set(i, cMonth);
			let daysInMonth = getDaysInMonth(year, i);
			for (let j = 1; j <= daysInMonth; j++) {
				let cDay = new CDay();
				cDay.year = year;
				cDay.month = i;
				cDay.day = j;
				cMonth.days.set(j, cDay);
			}
		}
	}
	else {
		cy = calendar.years.get(year) as CYear;
	}
	return cy;
}

/*
* 显示隐藏日期层
* dayDiv:日期层
* visible:是否可见
*/
function showOrHideDayDiv(dayDiv : DayDiv, visible : boolean) {
	let dayButtonSize = dayDiv.dayButtons.length;
	for (let i = 0; i < dayButtonSize; i++) {
		let dayButton = dayDiv.dayButtons[i];
		dayButton.visible = visible;
	}
}

/*
* 显示隐藏月层
* monthDiv:月层
* visible:是否可见
*/
function showOrHideMonthDiv(monthDiv : MonthDiv, visible : boolean) {
	let monthButtonSize = monthDiv.monthButtons.length;
	for (let i = 0; i < monthButtonSize; i++) {
		let monthButton = monthDiv.monthButtons[i];
		monthButton.visible = visible;
	}
}

/*
* 显示隐藏年层
* yearButtons:年层
* visible:是否可见
*/
function showOrHideYearDiv(yearDiv : YearDiv, visible : boolean) {
	let yearButtonSize = yearDiv.yearButtons.length;
	for (let i = 0; i < yearButtonSize; i++) {
		let yearButton = yearDiv.yearButtons[i];
		yearButton.visible = visible;
	}
}

/*
* 初始化日历
* calendar:日历
*/
function initCalendar(calendar : FCCalendar) {
	for (let i = 0; i < 42; i++) {
		let dayButton = new DayButton();
		calendar.dayDiv!.dayButtons.push(dayButton);
		let dayFCButtonm = new DayButton();
		dayFCButtonm.visible = false;
		calendar.dayDiv!.dayButtonsAm.push(dayFCButtonm);
	}
	for (let i = 0; i < 12; i++) {
		let monthButton = new MonthButton();
		monthButton.month = (i + 1);
		calendar.monthDiv!.monthButtons.push(monthButton);
		let monthButtonAm = new MonthButton();
		monthButtonAm.visible = false;
		monthButtonAm.month = (i + 1);
		calendar.monthDiv!.monthButtonsAm.push(monthButtonAm);
	}

	for (let i = 0; i < 12; i++) {
		let yearButton = new YearButton();
		calendar.yearDiv!.yearButtons.push(yearButton);
		let yearButtonAm = new YearButton();
		yearButtonAm.visible = false;
		calendar.yearDiv!.yearButtonsAm.push(yearButtonAm);
	}
}

/*
* 获取星期
* y:年
* m:月
* d:日
*/
function dayOfWeek(y : number, m : number, d : number) : number {
	return Math.floor(((d + 2 * m + 3 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400) + 1) % 7);
}

/*
* 获取当月
* calendar:日历
*/
function getMonth(calendar : FCCalendar) : CMonth {
	return getYear(calendar, calendar.selectedDay!.year).months.get(calendar.selectedDay!.month) as CMonth;
}

/*
* 获取下个月
* calendar:日历
* year:年
* month:月
*/
function getNextMonth(calendar : FCCalendar, year : number, month : number) : CMonth {
	let nextMonth = month + 1;
	let nextYear = year;
	if (nextMonth == 13) {
		nextMonth = 1;
		nextYear += 1;
	}
	return getYear(calendar, nextYear).months.get(nextMonth) as CMonth;
}

/*
* 获取上个月
* calendar:日历
* year:年
* month:月
*/
function getLastMonth(calendar : FCCalendar, year : number, month : number) : CMonth {
	let lastMonth = month - 1;
	let lastYear = year;
	if (lastMonth == 0) {
		lastMonth = 12;
		lastYear -= 1;
	}
	return getYear(calendar, lastYear).months.get(lastMonth) as CMonth;
}

/*
* 重置日期层布局
* calendar:日历
* dayDiv:日期层
* state:状态
*/
function resetDayDiv(calendar : FCCalendar, dayDiv : DayDiv, state : number) {
	let thisMonth = getMonth(calendar);
	let lastMonth = getLastMonth(calendar, thisMonth.year, thisMonth.month);
	let nextMonth = getNextMonth(calendar, thisMonth.year, thisMonth.month);
	let left = 0;
	let headHeight = calendar.headDiv!.bounds.bottom;
	let top = headHeight;
	let width = calendar.size.cx;
	let height = calendar.size.cy;
	height -= calendar.timeDiv!.bounds.bottom - calendar.timeDiv!.bounds.top;
	let dayButtonHeight = height - headHeight;
	if (dayButtonHeight < 1) {
		dayButtonHeight = 1;
	}
	let toY = 0;
	if (dayDiv.aDirection == 1) {
		toY = dayButtonHeight * dayDiv.aTick / dayDiv.aTotalTick;
		if (state == 1) {
			thisMonth = nextMonth;
			let month = thisMonth.month;
			lastMonth = getLastMonth(calendar, thisMonth.year, month);
			nextMonth = getNextMonth(calendar, thisMonth.year, month);
		}
	}
	else if (dayDiv.aDirection == 2) {
		toY = -dayButtonHeight * dayDiv.aTick / dayDiv.aTotalTick;
		if (state == 1) {
			thisMonth = lastMonth;
			let month = thisMonth.month;
			lastMonth = getLastMonth(calendar, thisMonth.year, month);
			nextMonth = getNextMonth(calendar, thisMonth.year, month);
		}
	}
	let buttonSize = 0;
	if (state == 0) {
		buttonSize = dayDiv.dayButtons.length;
	}
	else if (state == 1) {
		buttonSize = dayDiv.dayButtonsAm.length;
	}
	let dheight = dayButtonHeight / 6;
	let days = thisMonth.days;
	let firstDay = days.get(1) as CDay;
	let startDayOfWeek = dayOfWeek(firstDay.year, firstDay.month, firstDay.day);
	for (let i = 0; i < buttonSize; i++) {
		let dayButton : DayButton | null = null;
		if (state == 0) {
			dayButton = dayDiv.dayButtons[i];
			buttonSize = dayDiv.dayButtons.length;
		}
		else if (state == 1) {
			dayButton = dayDiv.dayButtonsAm[i];
			buttonSize = dayDiv.dayButtonsAm.length;
		}
		if (i == 35) {
			dheight = height - top;
		}
		let vOffset = 0;
		if (state == 1) {
			if (dayDiv.aTick > 0) {
				dayButton!.visible = true;
				if (dayDiv.aDirection == 1) {
					vOffset = toY - dayButtonHeight;
				}
				else if (dayDiv.aDirection == 2) {
					vOffset = toY + dayButtonHeight;

				}
			}
			else {
				dayButton!.visible = false;
				continue;
			}
		}
		else {
			vOffset = toY;
		}
		if ((i + 1) % 7 == 0) {
			let dp = new FCPoint(left, top + vOffset);
			let ds = new FCSize(width - left, dheight);
			let bounds = new FCRect(dp.x, dp.y, dp.x + ds.cx, dp.y + ds.cy);
			dayButton!.bounds = bounds;
			left = 0;
			if (i != 0 && i != buttonSize - 1) {
				top += dheight;
			}
		}
		else {
			let dp = new FCPoint(left, top + vOffset);
			let ds = new FCSize(width / 7 + ((i + 1) % 7) % 2, dheight);
			let bounds = new FCRect(dp.x, dp.y, dp.x + ds.cx, dp.y + ds.cy);
			dayButton!.bounds = bounds;
			left += ds.cx;
		}
		let cDay : CDay | null = null;
		dayButton!.inThisMonth = false;
		if (i >= startDayOfWeek && i <= startDayOfWeek + days.size - 1) {
			cDay = days.get(i - startDayOfWeek + 1) as CDay;
			dayButton!.inThisMonth = true;
		}
		else if (i < startDayOfWeek) {
			cDay = lastMonth.days.get(lastMonth.days.size - startDayOfWeek + i + 1) as CDay;
		}
		else if (i > startDayOfWeek + days.size - 1) {
			cDay = nextMonth.days.get(i - startDayOfWeek - days.size + 1) as CDay;
		}
		dayButton!.day = cDay;
		if (state == 0 && dayButton!.day != null && dayButton!.day == calendar.selectedDay) {
			dayButton!.selected = true;
		}
		else {
			dayButton!.selected = false;
		}
	}
}

/*
* 重置月层布局
* calendar:日历
* monthDiv:月层
* state:状态
*/
function resetMonthDiv(calendar : FCCalendar, monthDiv : MonthDiv, state : number) {
	let thisYear = monthDiv.year;
	let lastYear = monthDiv.year - 1;
	let nextYear = monthDiv.year + 1;
	let left = 0;
	let headHeight = calendar.headDiv!.bounds.bottom;
	let top = headHeight;
	let width = calendar.size.cx;
	let height = calendar.size.cy;
	height -= calendar.timeDiv!.bounds.bottom - calendar.timeDiv!.bounds.top;
	let monthButtonHeight = height - top;
	if (monthButtonHeight < 1) {
		monthButtonHeight = 1;
	}
	let toY = 0;
	let monthButtons : Array<MonthButton> = [];
	if (monthDiv.aDirection == 1) {
		toY = monthButtonHeight * monthDiv.aTick / monthDiv.aTotalTick;
		if (state == 1) {
			thisYear = nextYear;
			lastYear = thisYear - 1;
			nextYear = thisYear + 1;
		}
	}
	else if (monthDiv.aDirection == 2) {
		toY = -monthButtonHeight * monthDiv.aTick / monthDiv.aTotalTick;
		if (state == 1) {
			thisYear = lastYear;
			lastYear = thisYear - 1;
			nextYear = thisYear + 1;
		}
	}
	if (state == 0) {
		monthButtons = monthDiv.monthButtons;
	}
	else if (state == 1) {
		monthButtons = monthDiv.monthButtonsAm;
	}
	let dheight = monthButtonHeight / 3;
	let buttonSize = monthButtons.length;
	for (let i = 0; i < buttonSize; i++) {
		if (i == 8) {
			dheight = height - top;
		}
		let monthButton = monthButtons[i];
		monthButton.year = thisYear;
		let vOffSet = 0;
		if (state == 1) {
			if (monthDiv.aTick > 0) {
				monthButton.visible = true;
				if (monthDiv.aDirection == 1) {
					vOffSet = toY - monthButtonHeight;
				}
				else if (monthDiv.aDirection == 2) {
					vOffSet = toY + monthButtonHeight;
				}
			}
			else {
				monthButton.visible = false;
				continue;
			}
		}
		else {
			vOffSet = toY;
		}
		if ((i + 1) % 4 == 0) {
			let dp = new FCPoint(left, top + vOffSet);
			let ds = new FCSize(width - left, dheight);
			let bounds = new FCRect(dp.x, dp.y, dp.x + ds.cx, dp.y + ds.cy);
			monthButton.bounds = bounds;
			left = 0;
			if (i != 0 && i != buttonSize - 1) {
				top += dheight;
			}
		}
		else {
			let dp = new FCPoint(left, top + vOffSet);
			let ds = new FCSize(width / 4 + ((i + 1) % 4) % 2, dheight);
			let bounds = new FCRect(dp.x, dp.y, dp.x + ds.cx, dp.y + ds.cy);
			monthButton.bounds = bounds;
			left += ds.cx;
		}
	}
}

/*
* 重置年层布局
* calendar:日历
* yearDiv:年层
* state:状态
*/
function resetYearDiv(calendar : FCCalendar, yearDiv : YearDiv, state : number) {
	let thisStartYear = yearDiv.startYear;
	let lastStartYear = yearDiv.startYear - 12;
	let nextStartYear = yearDiv.startYear + 12;
	let left = 0;
	let headHeight = calendar.headDiv!.bounds.bottom;
	let top = headHeight;
	let width = calendar.size.cx;
	let height = calendar.size.cy;
	height -= calendar.timeDiv!.bounds.bottom - calendar.timeDiv!.bounds.top;
	let yearButtonHeight = height - top;
	if (yearButtonHeight < 1) {
		yearButtonHeight = 1;
	}
	let toY = 0;
	let yearButtons : Array<YearButton> = [];
	if (yearDiv.aDirection == 1) {
		toY = yearButtonHeight * yearDiv.aTick / yearDiv.aTotalTick;
		if (state == 1) {
			thisStartYear = nextStartYear;
			lastStartYear = thisStartYear - 12;
			nextStartYear = thisStartYear + 12;
		}
	}
	else if (yearDiv.aDirection == 2) {
		toY = -yearButtonHeight * yearDiv.aTick / yearDiv.aTotalTick;
		if (state == 1) {
			thisStartYear = lastStartYear;
			lastStartYear = thisStartYear - 12;
			nextStartYear = thisStartYear + 12;
		}
	}
	if (state == 0) {
		yearButtons = yearDiv.yearButtons;
	}
	else if (state == 1) {
		yearButtons = yearDiv.yearButtonsAm;
	}
	let dheight = yearButtonHeight / 3;
	let buttonSize = yearDiv.yearButtons.length;
	for (let i = 0; i < buttonSize; i++) {
		if (i == 8) {
			dheight = height - top;
		}
		let yearButton = yearButtons[i];
		yearButton.year = thisStartYear + i;
		let vOffSet = 0;
		if (state == 1) {
			if (yearDiv.aTick > 0) {
				yearButton.visible = true;
				if (yearDiv.aDirection == 1) {
					vOffSet = toY - yearButtonHeight;
				}
				else if (yearDiv.aDirection == 2) {
					vOffSet = toY + yearButtonHeight;
				}
			}
			else {
				yearButton.visible = false;
				continue;
			}
		}
		else {
			vOffSet = toY;
		}
		if ((i + 1) % 4 == 0) {
			let dp = new FCPoint(left, top + vOffSet);
			let ds = new FCSize(width - left, dheight);
			let bounds = new FCRect(dp.x, dp.y, dp.x + ds.cx, dp.y + ds.cy);
			yearButton.bounds = bounds;
			left = 0;
			if (i != 0 && i != buttonSize - 1) {
				top += dheight;
			}
		}
		else {
			let dp = new FCPoint(left, top + vOffSet);
			let ds = new FCSize(width / 4 + ((i + 1) % 4) % 2, dheight);
			let bounds = new FCRect(dp.x, dp.y, dp.x + ds.cx, dp.y + ds.cy);
			yearButton.bounds = bounds;
			left += ds.cx;
		}
	}
}

/*
* 选择开始年份
* yearDiv:年层
* startYear:开始年
*/
function selectStartYear(calendar : FCCalendar, yearDiv : YearDiv, startYear : number) {
	if (yearDiv.startYear != startYear) {
		if (startYear > yearDiv.startYear) {
			yearDiv.aDirection = 1;
		}
		else {
			yearDiv.aDirection = 2;
		}
		if (calendar.useAnimation) {
			yearDiv.aTick = yearDiv.aTotalTick;
		}
		yearDiv.startYear = startYear;
	}
}

/*
* 选择年份
* calendar:日历
* monthDiv:月层
* year:年
*/
function selectYear(calendar : FCCalendar, monthDiv : MonthDiv, year : number) {
	if (monthDiv.year != year) {
		if (year > monthDiv.year) {
			monthDiv.aDirection = 1;
		}
		else {
			monthDiv.aDirection = 2;
		}
		if (calendar.useAnimation) {
			monthDiv.aTick = monthDiv.aTotalTick;
		}
		monthDiv.year = year;
	}
}

/*
* 选中日期
* calendar:日历
* dayDiv:日期层
* selectedDay:选中日
* lastDay:上一日
*/
function selectDay(calendar : FCCalendar, dayDiv : DayDiv, selectedDay : CDay, lastDay : CDay) {
	let m = getYear(calendar, selectedDay.year).months.get(selectedDay.month) as CMonth;
	let thisMonth = getYear(calendar, lastDay.year).months.get(lastDay.month) as CMonth;
	if (m != thisMonth) {
		if (thisMonth.year * 12 + thisMonth.month > m.year * 12 + m.month) {
			dayDiv.aDirection = 2;
		}
		else {
			dayDiv.aDirection = 1;
		}
		let i = 0;
		let buttonSize = dayDiv.dayButtons.length;
		for (i = 0; i < buttonSize; i++) {
			let dayButton = dayDiv.dayButtons[i];
			if ((dayDiv.aDirection == 1 && dayButton.day == thisMonth.days.get(0))
				|| (dayDiv.aDirection == 2 && dayButton.day == thisMonth.days.get(thisMonth.days.size - 1))) {
				dayDiv.aClickRowFrom = i / 7;
				if (i % 7 != 0) {
					dayDiv.aClickRowFrom += 1;
				}
			}
		}
		resetDayDiv(calendar, dayDiv, 0);
		buttonSize = dayDiv.dayButtonsAm.length;
		for (i = 0; i < buttonSize; i++) {
			let dayFCButtonm = dayDiv.dayButtonsAm[i];
			if ((dayDiv.aDirection == 1 && dayFCButtonm.day == m.days.get(0))
				|| (dayDiv.aDirection == 2 && dayFCButtonm.day == m.days.get(m.days.size - 1))) {
				dayDiv.aClickRowTo = i / 7;
				if (i % 7 != 0) {
					dayDiv.aClickRowTo += 1;
				}
			}
		}

		if (calendar.useAnimation) {
			dayDiv.aTick = dayDiv.aTotalTick;
		}
	} else {
		let dayButtonsSize = dayDiv.dayButtons.length;
		for (let i = 0; i < dayButtonsSize; i++) {
			let dayButton = dayDiv.dayButtons[i];
			if (dayButton.day != selectedDay) {
				dayButton.selected = false;
			}
		}
	}
}

/*
* 更新日历的布局
* calendar:日历
*/
function updateCalendar(calendar : FCCalendar) {
	calendar.headDiv!.bounds = new FCRect(0, 0, calendar.size.cx, 80);
	if (calendar.mode == "day") {
		resetDayDiv(calendar, calendar.dayDiv!, 0);
		resetDayDiv(calendar, calendar.dayDiv!, 1);
	} else if (calendar.mode == "month") {
		resetMonthDiv(calendar, calendar.monthDiv!, 0);
		resetMonthDiv(calendar, calendar.monthDiv!, 1);
	}
	else if (calendar.mode == "year") {
		resetYearDiv(calendar, calendar.yearDiv!, 0);
		resetYearDiv(calendar, calendar.yearDiv!, 1);
	}
}

/*
* 绘制头部层
* calendar:日历
* headDiv:头部层
* paint:绘图对象
*/
function drawHeadDiv(calendar : FCCalendar, headDiv : HeadDiv, paint : FCPaint) {
	let bounds = headDiv.bounds;
	if (headDiv.backColor != null && headDiv.backColor != "none") {
		paint.fillRect(headDiv.backColor, bounds.left, bounds.top, bounds.right, bounds.bottom);
	}
	let weekStrings : Array<string> = [];
	weekStrings.push("周日");
	weekStrings.push("周一");
	weekStrings.push("周二");
	weekStrings.push("周三");
	weekStrings.push("周四");
	weekStrings.push("周五");
	weekStrings.push("周六");
	let w = bounds.right - bounds.left;
	let left = bounds.left;
	for (let i = 0; i < 7; i++) {
		let weekDaySize = paint.textSize(weekStrings[i], headDiv.weekFont);
		let textX = left + (w / 7) / 2 - weekDaySize.cx / 2;
		let textY = bounds.bottom - weekDaySize.cy - 2;
		paint.drawText(weekStrings[i], headDiv.textColor, headDiv.weekFont, textX, textY);
		left += w / 7;
	}
	let drawTitle = "";
	if (calendar.mode == "day") {
		drawTitle = calendar.selectedDay!.year + "年" + calendar.selectedDay!.month + "月";
	} else if (calendar.mode == "month") {
		drawTitle = calendar.monthDiv!.year + "年";
	} else {
		drawTitle = calendar.yearDiv!.startYear + "年-" + (calendar.yearDiv!.startYear + 11) + "年";
	}
	let tSize = paint.textSize(drawTitle, headDiv.titleFont);
	paint.drawText(drawTitle, headDiv.textColor, headDiv.titleFont, bounds.left + (w - tSize.cx) / 2, 30);
	let tR = 10;
	//画左右三角
	paint.beginPath();
	paint.addLine(5, bounds.top + (bounds.bottom - bounds.top) / 2, 5 + tR * 2, bounds.top + (bounds.bottom - bounds.top) / 2 - tR);
	paint.addLine(5 + tR * 2, bounds.top + (bounds.bottom - bounds.top) / 2 - tR, 5 + tR * 2, bounds.top + (bounds.bottom - bounds.top) / 2 + tR);
	paint.addLine(5 + tR * 2, bounds.top + (bounds.bottom - bounds.top) / 2 + tR, 5, bounds.top + (bounds.bottom - bounds.top) / 2);
	paint.fillPath(headDiv.arrowColor);
	paint.closePath();

	paint.beginPath();
	paint.addLine(bounds.right - 5, bounds.top + (bounds.bottom - bounds.top) / 2, bounds.right - 5 - tR * 2, bounds.top + (bounds.bottom - bounds.top) / 2 - tR);
	paint.addLine(bounds.right - 5 - tR * 2, bounds.top + (bounds.bottom - bounds.top) / 2 - tR, bounds.right - 5 - tR * 2, bounds.top + (bounds.bottom - bounds.top) / 2 + tR);
	paint.addLine(bounds.right - 5 - tR * 2, bounds.top + (bounds.bottom - bounds.top) / 2 + tR, bounds.right - 5, bounds.top + (bounds.bottom - bounds.top) / 2);
	paint.fillPath(headDiv.arrowColor);
	paint.closePath();
}

/*
* 绘制日的按钮
* calendar:日历
* dayButton:日期按钮
* paint:绘图对象 
*/
function drawDayButton(calendar : FCCalendar, dayButton : DayButton, paint : FCPaint) {
	if (dayButton.day != null) {
		let bounds = dayButton.bounds;
		let text = dayButton.day!.day.toString();
		let tSize = paint.textSize(text, dayButton.font);
		if (dayButton.backColor != null && dayButton.backColor != "none") {
			paint.fillRect(dayButton.backColor!, bounds.left + 2, bounds.top + 2, bounds.right - 2, bounds.bottom - 2);
		}
		if (dayButton.inThisMonth) {
			paint.drawText(text, dayButton.textColor, dayButton.font, bounds.left + 5, bounds.top + 7);
		} else {
			paint.drawText(text, dayButton.textColor2, dayButton.font, bounds.left + 5, bounds.top + 7);
		}
		if (dayButton.borderColor != null && dayButton.borderColor != "none") {
			paint.drawRect(dayButton.borderColor, 1, null, bounds.left + 2, bounds.top + 2, bounds.right - 2, bounds.bottom - 2);
		}
	}
}

/*
* 绘制月的按钮
* calendar:日历
* monthButton:月按钮
* paint:绘图对象
*/
function drawMonthButton(calendar : FCCalendar, monthButton : MonthButton, paint : FCPaint) {
	let bounds = monthButton.bounds;
	let text = getMonthStr(monthButton.month);
	let tSize = paint.textSize(text, monthButton.font);
	if (monthButton.backColor != null && monthButton.backColor != "none") {
		paint.fillRect(monthButton.backColor!, bounds.left + 2, bounds.top + 2, bounds.right - 2, bounds.bottom - 2);
	}
	paint.drawText(text, monthButton.textColor, monthButton.font, bounds.left + 5, bounds.top + 7);
	if (monthButton.borderColor != null && monthButton.borderColor != "none") {
		paint.drawRect(monthButton.borderColor, 1, null, bounds.left + 2, bounds.top + 2, bounds.right - 2, bounds.bottom - 2);
	}
}

/*
* 绘制年的按钮
* calendar:日历
* yearButton:年按钮
* paint:绘图对象
*/
function drawYearButton(calendar : FCCalendar, yearButton : YearButton, paint : FCPaint) {
	let bounds = yearButton.bounds;
	let text = yearButton.year.toString();
	let tSize = paint.textSize(text, yearButton.font);
	if (yearButton.backColor != null && yearButton.backColor != "none") {
		paint.fillRect(yearButton.backColor!, bounds.left + 2, bounds.top + 2, bounds.right - 2, bounds.bottom - 2);
	}
	paint.drawText(text, yearButton.textColor, yearButton.font, bounds.left + 5, bounds.top + 7);
	if (yearButton.borderColor != null && yearButton.borderColor != "none") {
		paint.drawRect(yearButton.borderColor!, 1, null, bounds.left + 2, bounds.top + 2, bounds.right - 2, bounds.bottom - 2);
	}
}

/*
* 绘制日历
* calendar:日历
* paint:绘图对象
*/
function drawCalendar(calendar : FCCalendar, paint : FCPaint) {
	if (calendar.backColor != null && calendar.backColor != "none") {
		paint.fillRect(calendar.backColor, 0, 0, calendar.size.cx, calendar.size.cy);
	}
	if (calendar.mode == "day") {
		let dayButtonsSize = calendar.dayDiv!.dayButtons.length;
		for (let i = 0; i < dayButtonsSize; i++) {
			let dayButton = calendar.dayDiv!.dayButtons[i];
			if (dayButton.visible) {
				if (paint.onPaintCalendarDayButton != null) {
					paint.onPaintCalendarDayButton!(calendar, dayButton, paint);
				} else {
					drawDayButton(calendar, dayButton, paint);
				}
			}
		}
		let dayFCButtonmSize = calendar.dayDiv!.dayButtonsAm.length;
		for (let i = 0; i < dayFCButtonmSize; i++) {
			let dayButton = calendar.dayDiv!.dayButtonsAm[i];
			if (dayButton.visible) {
				if (paint.onPaintCalendarDayButton != null) {
					paint.onPaintCalendarDayButton!(calendar, dayButton, paint);
				} else {
					drawDayButton(calendar, dayButton, paint);
				}
			}
		}
	}
	else if (calendar.mode == "month") {
		let monthButtonsSize = calendar.monthDiv!.monthButtons.length;
		for (let i = 0; i < monthButtonsSize; i++) {
			let monthButton = calendar.monthDiv!.monthButtons[i];
			if (monthButton.visible) {
				if (paint.onPaintCalendarMonthButton != null) {
					paint.onPaintCalendarMonthButton!(calendar, monthButton, paint);
				} else {
					drawMonthButton(calendar, monthButton, paint);
				}
			}
		}
		let monthFCButtonmSize = calendar.monthDiv!.monthButtonsAm.length;
		for (let i = 0; i < monthFCButtonmSize; i++) {
			let monthButton = calendar.monthDiv!.monthButtonsAm[i];
			if (monthButton.visible) {
				if (paint.onPaintCalendarMonthButton != null) {
					paint.onPaintCalendarMonthButton!(calendar, monthButton, paint);
				} else {
					drawMonthButton(calendar, monthButton, paint);
				}
			}
		}
	} else if (calendar.mode == "year") {
		let yearButtonsSize = calendar.yearDiv!.yearButtons.length;
		for (let i = 0; i < yearButtonsSize; i++) {
			let yearButton = calendar.yearDiv!.yearButtons[i];
			if (yearButton.visible) {
				if (paint.onPaintCalendarYearButton != null) {
					paint.onPaintCalendarYearButton!(calendar, yearButton, paint);
				} else {
					drawYearButton(calendar, yearButton, paint);
				}
			}
		}
		let yearFCButtonmSize = calendar.yearDiv!.yearButtonsAm.length;
		for (let i = 0; i < yearFCButtonmSize; i++) {
			let yearButton = calendar.yearDiv!.yearButtonsAm[i];
			if (yearButton.visible) {
				if (paint.onPaintCalendarYearButton != null) {
					paint.onPaintCalendarYearButton!(calendar, yearButton, paint);
				} else {
					drawYearButton(calendar, yearButton, paint);
				}
			}
		}
	}
	if (paint.onPaintHeadDiv != null) {
		paint.onPaintHeadDiv!(calendar, calendar.headDiv!, paint);
	} else {
		drawHeadDiv(calendar, calendar.headDiv!, paint);
	}
	if (calendar.borderColor != null) {
		paint.drawRect(calendar.borderColor!, 1, null, 0, 0, calendar.size.cx, calendar.size.cy);
	}
}

/*
* 点击日的按钮
* calendar:日历
* dayButton:日期按钮
* mp:坐标
*/
function clickDayButton(calendar : FCCalendar, dayButton : DayButton, mp : FCPoint) {
	let lastDay = calendar.selectedDay as CDay;
	calendar.selectedDay = dayButton.day;
	selectDay(calendar, calendar.dayDiv!, calendar.selectedDay!, lastDay!);
	updateCalendar(calendar);
	if (calendar.paint != null) {
		invalidateView(calendar);
	}
}

/*
* 点击月的按钮
* calendar:日历
* monthButton:月按钮
* mp:坐标
*/
function clickMonthButton(calendar : FCCalendar, monthButton : MonthButton, mp : FCPoint) {
	let month = getYear(calendar, monthButton.year).months.get(monthButton.month) as CMonth;
	calendar.mode = "day";
	let lastDay = calendar.selectedDay;
	calendar.selectedDay = month.days.get(1) as CDay;
	selectDay(calendar, calendar.dayDiv!, calendar.selectedDay!, lastDay!);
	updateCalendar(calendar);
	if (calendar.paint != null) {
		invalidateView(calendar);
	}
}

/*
* 点击年的按钮
* calendar:日历
* yearButton:年按钮
* mp:坐标
*/
function clickYearButton(calendar : FCCalendar, yearButton : YearButton, mp : FCPoint) {
	calendar.mode = "month";
	selectYear(calendar, calendar.monthDiv!, yearButton.year);
	updateCalendar(calendar);
	if (calendar.paint != null) {
		invalidateView(calendar);
	}
}

/*
* 点击左侧的按钮
* calendar:日历
* headDiv:头部层
* mp:坐标
*/
function clickLastButton(calendar : FCCalendar, headDiv : HeadDiv, mp : FCPoint) {
	if (calendar.mode == "day") {
		let lastMonth = getLastMonth(calendar, calendar.selectedDay!.year, calendar.selectedDay!.month);
		let lastDay = calendar.selectedDay;
		calendar.selectedDay = lastMonth.days.get(1) as CDay;
		selectDay(calendar, calendar.dayDiv!, calendar.selectedDay!, lastDay!);
		updateCalendar(calendar);
		if (calendar.paint != null) {
			invalidateView(calendar);
		}
	} else if (calendar.mode == "month") {
		let year = calendar.monthDiv!.year;
		year -= 1;
		selectYear(calendar, calendar.monthDiv!, year);
		updateCalendar(calendar);
		if (calendar.paint != null) {
			invalidateView(calendar);
		}
	} else if (calendar.mode == "year") {
		let year = calendar.yearDiv!.startYear;
		year -= 12;
		selectStartYear(calendar, calendar.yearDiv!, year);
		updateCalendar(calendar);
		if (calendar.paint != null) {
			invalidateView(calendar);
		}
	}
}

/*
* 点击右侧的按钮
* calendar:日历
* headDiv:头部层
* mp:坐标
*/
function clickNextButton(calendar : FCCalendar, headDiv : HeadDiv, mp : FCPoint) {
	if (calendar.mode == "day") {
		let nextMonth = getNextMonth(calendar, calendar.selectedDay!.year, calendar.selectedDay!.month);
		let lastDay = calendar.selectedDay;
		calendar.selectedDay = nextMonth.days.get(1) as CDay;
		selectDay(calendar, calendar.dayDiv!, calendar.selectedDay!, lastDay!);
		updateCalendar(calendar);
		if (calendar.paint != null) {
			invalidateView(calendar);
		}
	} else if (calendar.mode == "month") {
		let year = calendar.monthDiv!.year;
		year += 1;
		selectYear(calendar, calendar.monthDiv!, year);
		updateCalendar(calendar);
		if (calendar.paint != null) {
			invalidateView(calendar);
		}
	} else if (calendar.mode == "year") {
		let year = calendar.yearDiv!.startYear;
		year += 12;
		selectStartYear(calendar, calendar.yearDiv!, year);
		updateCalendar(calendar);
		if (calendar.paint != null) {
			invalidateView(calendar);
		}
	}
}

/*
* 改变模式的按钮
* calendar:日历
* headDiv:头部层
* mp:坐标
*/
function clickModeButton(calendar : FCCalendar, headDiv : HeadDiv, mp : FCPoint) {
	if (calendar.mode == "day") {
		calendar.mode = "month";
		calendar.monthDiv!.month = calendar.selectedDay!.month;
		calendar.monthDiv!.year = calendar.selectedDay!.year;
		updateCalendar(calendar);
		if (calendar.paint != null) {
			invalidateView(calendar);
		}
	}
	else if (calendar.mode == "month") {
		calendar.mode = "year";
		selectStartYear(calendar, calendar.yearDiv!, calendar.monthDiv!.year);
		updateCalendar(calendar);
		if (calendar.paint != null) {
			invalidateView(calendar);
		}
	}
}

/*
* 点击日历
* calendar:日历
* mp:坐标
*/
function clickCalendar(calendar : FCCalendar, mp : FCPoint) {
	let headBounds = calendar.headDiv!.bounds;
	if (mp.x >= headBounds.left && mp.x <= headBounds.right && mp.y >= headBounds.top && mp.y <= headBounds.bottom) {
		let tR = 10;
		if (mp.x < headBounds.left + tR * 3) {
			clickLastButton(calendar, calendar.headDiv!, mp);
			return;
		} else if (mp.x > headBounds.right - tR * 3) {
			clickNextButton(calendar, calendar.headDiv!, mp);
			return;
		} else {
			clickModeButton(calendar, calendar.headDiv!, mp);
			return;
		}
	}
	if (calendar.mode == "day") {
		let dayButtonsSize = calendar.dayDiv!.dayButtons.length;
		for (let i = 0; i < dayButtonsSize; i++) {
			let dayButton = calendar.dayDiv!.dayButtons[i];
			if (dayButton.visible) {
				let bounds = dayButton.bounds;
				if (mp.x >= bounds.left && mp.x <= bounds.right && mp.y >= bounds.top && mp.y <= bounds.bottom) {
					clickDayButton(calendar, dayButton, mp);
					return;
				}
			}
		}
	}
	else if (calendar.mode == "month") {
		let monthButtonsSize = calendar.monthDiv!.monthButtons.length;
		for (let i = 0; i < monthButtonsSize; i++) {
			let monthButton = calendar.monthDiv!.monthButtons[i];
			if (monthButton.visible) {
				let bounds = monthButton.bounds;
				if (mp.x >= bounds.left && mp.x <= bounds.right && mp.y >= bounds.top && mp.y <= bounds.bottom) {
					clickMonthButton(calendar, monthButton, mp);
					return;
				}
			}
		}
	} else if (calendar.mode == "year") {
		let yearButtonsSize = calendar.yearDiv!.yearButtons.length;
		for (let i = 0; i < yearButtonsSize; i++) {
			let yearButton = calendar.yearDiv!.yearButtons[i];
			if (yearButton.visible) {
				let bounds = yearButton.bounds;
				if (mp.x >= bounds.left && mp.x <= bounds.right && mp.y >= bounds.top && mp.y <= bounds.bottom) {
					clickYearButton(calendar, yearButton, mp);
					return;
				}
			}
		}
	}
}

/*
* 绘制滚动条
* div:图层
* paint:绘图对象
* clipRect:裁剪区域
*/
function drawDivScrollBar(div : FCDiv, paint : FCPaint, clipRect : FCRect) {
	div.hScrollIsVisible = false;
	div.vScrollIsVisible = false;
	if (paint.isMobile) {
		if (paint.touchDownView == div) {
		} else if (g_dragScrollView_Div == div && g_scrollAddSpeed_Div != 0) {
		} else {
			return;
		}
	}
	//绘制滚动条
	if (div.showHScrollBar) {
		let contentWidth = getDivContentWidth((div as any) as FCView);
		if (contentWidth > 0 && contentWidth > div.size.cx) {
			let sLeft = div.scrollH / contentWidth * div.size.cx;
			let sRight = (div.scrollH + div.size.cx) / contentWidth * div.size.cx;
			if (sRight - sLeft < div.scrollSize) {
				sRight = sLeft + div.scrollSize;
			}
			if (paint.touchMoveView == div && (div.hoverScrollHButton || div.downScrollHButton)) {
				paint.fillRect(div.scrollBarHoveredColor, sLeft, div.size.cy - div.scrollSize, sRight, div.size.cy);
			} else {
				paint.fillRect(div.scrollBarColor, sLeft, div.size.cy - div.scrollSize, sRight, div.size.cy);
			}
			div.hScrollIsVisible = true;
		}
	}
	if (div.showVScrollBar) {
		let contentHeight = getDivContentHeight((div as any) as FCView);
		if (contentHeight > 0 && contentHeight > div.size.cy) {
			let sTop = div.scrollV / contentHeight * div.size.cy;
			let sBottom = sTop + (div.size.cy / contentHeight * div.size.cy);
			if (sBottom - sTop < div.scrollSize) {
				sBottom = sTop + div.scrollSize;
			}
			if (paint.touchMoveView == div && (div.hoverScrollVButton || div.downScrollVButton)) {
				paint.fillRect(div.scrollBarHoveredColor, div.size.cx - div.scrollSize, sTop, div.size.cx, sBottom);
			} else {
				paint.fillRect(div.scrollBarColor, div.size.cx - div.scrollSize, sTop, div.size.cx, sBottom);
			}
			div.vScrollIsVisible = true;
		}
	}
}

/*
* 获取内容的宽度
* div:图层
*/
function getDivContentWidth(div : FCView) : number {
	let cWidth = 0;
	for (let i = 0; i < div.views.length; i++) {
		if (div.views[i].visible) {
			if (cWidth < div.views[i].location.x + div.views[i].size.cx) {
				cWidth = div.views[i].location.x + div.views[i].size.cx;
			}
		}
	}
	return cWidth;
}

/*
* 获取内容的高度
* div:图层
*/
function getDivContentHeight(div : FCView) : number {
	let cHeight = 0;
	for (let i = 0; i < div.views.length; i++) {
		if (div.views[i].visible) {
			if (cHeight < div.views[i].location.y + div.views[i].size.cy) {
				cHeight = div.views[i].location.y + div.views[i].size.cy;
			}
		}
	}
	return cHeight;
}

/*
* 图层的鼠标移动方法
* div: 图层
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
*/
function touchMoveDiv(div : FCDiv, firstTouch : boolean, firstPoint : FCPoint, secondTouch : boolean, secondPoint : FCPoint) {
	div.hoverScrollHButton = false;
	div.hoverScrollVButton = false;
	let mp = firstPoint;
	if (firstTouch) {
		if (div.showHScrollBar || div.showVScrollBar) {
			if (div.downScrollHButton) {
				let contentWidth = getDivContentWidth((div as any) as FCView);
				let subX = (mp.x - div.startPoint.x) / div.size.cx * contentWidth;
				let newScrollH = div.startScrollH + subX;
				if (newScrollH < 0) {
					newScrollH = 0;
				} else if (newScrollH > contentWidth - div.size.cx) {
					newScrollH = contentWidth - div.size.cx;
				}
				div.scrollH = newScrollH;
				div.paint!.cancelClick = true;
				return;

			} else if (div.downScrollVButton) {
				let contentHeight = getDivContentHeight((div as any) as FCView);
				let subY = (mp.y - div.startPoint.y) / div.size.cy * contentHeight;
				let newScrollV = div.startScrollV + subY;
				if (newScrollV < 0) {
					newScrollV = 0;
				} else if (newScrollV > contentHeight - div.size.cy) {
					newScrollV = contentHeight - div.size.cy;
				}
				div.scrollV = newScrollV;
				div.paint!.cancelClick = true;
				return;
			}
		}
		if (div.allowDragScroll) {
			let contentWidth = getDivContentWidth((div as any) as FCView);
			if (contentWidth > div.size.cx) {
				let subX = div.startPoint.x - mp.x;
				let newScrollH = div.startScrollH + subX;
				if (newScrollH < 0) {
					newScrollH = 0;
				} else if (newScrollH > contentWidth - div.size.cx) {
					newScrollH = contentWidth - div.size.cx;
				}
				div.scrollH = newScrollH;
				if (Math.abs(subX) > 5) {
					div.paint!.cancelClick = true;
				}
			}
			let contentHeight = getDivContentHeight((div as any) as FCView);
			if (contentHeight > div.size.cy) {
				let subY = div.startPoint.y - mp.y;
				let newScrollV = div.startScrollV + subY;
				if (newScrollV < 0) {
					newScrollV = 0;
				} else if (newScrollV > contentHeight - div.size.cy) {
					newScrollV = contentHeight - div.size.cy;
				}
				div.scrollV = newScrollV;
				if (Math.abs(subY) > 5) {
					div.paint!.cancelClick = true;
				}
			}
		}
	} else {
		if (div.showHScrollBar) {
			let contentWidth = getDivContentWidth((div as any) as FCView);
			if (contentWidth > 0 && contentWidth > div.size.cx) {
				let sLeft = div.scrollH / contentWidth * div.size.cx;
				let sRight = (div.scrollH + div.size.cx) / contentWidth * div.size.cx;
				if (sRight - sLeft < div.scrollSize) {
					sRight = sLeft + div.scrollSize;
				}
				if (mp.x >= sLeft && mp.x <= sRight && mp.y >= div.size.cy - div.scrollSize && mp.y <= div.size.cy) {
					div.hoverScrollHButton = true;
					return;
				} else {
					div.hoverScrollHButton = false;
				}
			}
		}
		if (div.showVScrollBar) {
			let contentHeight = getDivContentHeight((div as any) as FCView);
			if (contentHeight > 0 && contentHeight > div.size.cy) {
				let sTop = div.scrollV / contentHeight * div.size.cy;
				let sBottom = (div.scrollV + div.size.cy) / contentHeight * div.size.cy;
				if (sBottom - sTop < div.scrollSize) {
					sBottom = sTop + div.scrollSize;
				}
				if (mp.x >= div.size.cx - div.scrollSize && mp.x <= div.size.cx && mp.y >= sTop && mp.y <= sBottom) {
					div.hoverScrollVButton = true;
					return;
				} else {
					div.hoverScrollVButton = false;
				}
			}
		}
	}
}

/*
* 图层的鼠标按下方法
* div: 图层
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
* clicks:点击次数
*/
function touchDownDiv(div : FCDiv, firstTouch : boolean, firstPoint : FCPoint, secondTouch : boolean, secondPoint : FCPoint, clicks : number) {
	let mp = firstPoint;
	div.touchDownTime = new Date().getTime()
	div.startPoint = mp;
	div.downScrollHButton = false;
	div.downScrollVButton = false;
	div.hoverScrollHButton = false;
	div.hoverScrollVButton = false;
	g_dragScrollView_Div = null;
	g_scrollAddSpeed_Div = 0;
	g_scrollDirection_Div = 0;
	if (div.showHScrollBar) {
		let contentWidth = getDivContentWidth((div as any) as FCView);
		if (contentWidth > 0 && contentWidth > div.size.cx) {
			let sLeft = div.scrollH / contentWidth * div.size.cx;
			let sRight = (div.scrollH + div.size.cx) / contentWidth * div.size.cx;
			if (sRight - sLeft < div.scrollSize) {
				sRight = sLeft + div.scrollSize;
			}
			if (mp.x >= sLeft && mp.x <= sRight && mp.y >= div.size.cy - div.scrollSize && mp.y <= div.size.cy) {
				div.downScrollHButton = true;
				div.startScrollH = div.scrollH;
				return;
			}
		}
	}
	if (div.showVScrollBar) {
		let contentHeight = getDivContentHeight((div as any) as FCView);
		if (contentHeight > 0 && contentHeight > div.size.cy) {
			let sTop = div.scrollV / contentHeight * div.size.cy;
			let sBottom = (div.scrollV + div.size.cy) / contentHeight * div.size.cy;
			if (sBottom - sTop < div.scrollSize) {
				sBottom = sTop + div.scrollSize;
			}
			if (mp.x >= div.size.cx - div.scrollSize && mp.x <= div.size.cx && mp.y >= sTop && mp.y <= sBottom) {
				div.downScrollVButton = true;
				div.startScrollV = div.scrollV;
				return;
			}
		}
	}
	if (div.allowDragScroll) {
		div.startScrollH = div.scrollH;
		div.startScrollV = div.scrollV;
	}
}

let g_dragScrollView_Div : FCDiv | null = null;//正在滚动的表格
let g_scrollAddSpeed_Div : number = 0;//滚动加速
let g_scrollDirection_Div : number = 0; //滚动方向

/*
* 检查拖动滚动
*/
function checkDragScroll_Div() {
	if (g_dragScrollView_Div != null) {
		let sub = Math.floor(g_scrollAddSpeed_Div / 10);
		if (sub == 0 && g_scrollAddSpeed_Div > 1) {
			sub = 1;
		} else if (sub == 0 && g_scrollAddSpeed_Div < -1) {
			sub = -1;
		}
		g_scrollAddSpeed_Div -= sub;
		if (sub == 0) {
			let viewCache = g_dragScrollView_Div as FCDiv;
			g_scrollAddSpeed_Div = 0;
			g_dragScrollView_Div = null;
			if (viewCache.paint != null) {
				invalidateView(viewCache);
			}
		} else {
			let viewCache = g_dragScrollView_Div as FCDiv;
			let oldScrollV = Math.floor(viewCache.scrollV + g_scrollAddSpeed_Div);
			let oldScrollH = Math.floor(viewCache.scrollH + g_scrollAddSpeed_Div);
			if (g_scrollDirection_Div == 0) {
				let contentHeight = getDivContentHeight(viewCache);
				if (contentHeight < viewCache.size.cy) {
					viewCache.scrollV = 0;
				} else {
					if (oldScrollV < 0) {
						oldScrollV = 0;
					} else if (oldScrollV > contentHeight - viewCache.size.cy) {
						oldScrollV = contentHeight - viewCache.size.cy;
					}
					viewCache.scrollV = oldScrollV;
				}
			} else {
				let contentWidth = getDivContentWidth(viewCache);
				if (contentWidth < viewCache.size.cx) {
					viewCache.scrollH = 0;
				} else {
					if (oldScrollH < 0) {
						oldScrollH = 0;
					} else if (oldScrollH > contentWidth - viewCache.size.cx) {
						oldScrollH = contentWidth - viewCache.size.cx;
					}
					viewCache.scrollH = oldScrollH;
				}
			}
			if (viewCache.paint != null) {
				invalidateView(viewCache);
			}
		}
	}
}

/*
* 图层的鼠标抬起方法
* div: 图层
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
* clicks:点击次数
*/
function touchUpDiv(div : FCDiv, firstTouch : boolean, firstPoint : FCPoint, secondTouch : boolean, secondPoint : FCPoint, clicks : number) {
	div.hoverScrollHButton = false;
	div.hoverScrollVButton = false;
	if (firstTouch && !div.downScrollHButton && !div.downScrollVButton) {
		if (div.allowDragScroll) {
			let touchUpTime = new Date().getTime();
			let diff = touchUpTime - div.touchDownTime;
			//加速滚动
			if (diff < 250) {
				let sub1 = 100 * ((Math.abs(firstPoint.y - div.startPoint.y)) / 20) / diff * 10;
				let sub2 = 100 * ((Math.abs(firstPoint.x - div.startPoint.x)) / 20) / diff * 10;
				if ("A:" + sub1 != "A:NaN" && "A:" + sub2 != "A:NaN") {
					if (Math.abs(sub1) > Math.abs(sub2)) {
						if (firstPoint.y < div.startPoint.y) {
							g_scrollAddSpeed_Div += sub1;
						} else {
							g_scrollAddSpeed_Div -= sub1;
						}
						g_scrollDirection_Div = 0;
					} else {
						if (firstPoint.x < div.startPoint.x) {
							g_scrollAddSpeed_Div += sub2;
						} else {
							g_scrollAddSpeed_Div -= sub2;
						}
						g_scrollDirection_Div = 1;
					}
					g_dragScrollView_Div = div;
					if (Math.abs(g_scrollAddSpeed_Div) > 0) {
						div.paint!.cancelClick = true;
					}
				}
			}
		}
	}
	div.downScrollHButton = false;
	div.downScrollVButton = false;
}

/*
* 图层的鼠标滚轮方法
* div:图层
* delta:滚轮值
*/
function touchWheelDiv(div : FCDiv, delta : number) {
	let oldScrollV = div.scrollV;
	if (delta < 0) {
		oldScrollV -= 10;
	} else if (delta > 0) {
		oldScrollV += 10;
	}
	let contentHeight = getDivContentHeight((div as any) as FCView);
	if (contentHeight < div.size.cy) {
		div.scrollV = 0;
	} else {
		if (oldScrollV < 0) {
			oldScrollV = 0;
		} else if (oldScrollV > contentHeight - div.size.cy) {
			oldScrollV = contentHeight - div.size.cy;
		}
		div.scrollV = oldScrollV;
	}
}

/*
* 重绘图层
* div:视图
* paint:绘图对象
* clipRect:裁剪区域
*/
function drawDiv(div : FCView, paint : FCPaint, clipRect : FCRect) {
	if (div.backColor != null && div.backColor != "none") {
		paint.fillRoundRect(div.backColor, 0, 0, div.size.cx, div.size.cy, div.cornerRadius);
	}
}

/*
* 重绘图层边线
* div:视图
* paint:绘图对象
* clipRect:裁剪区域
*/
function drawDivBorder(div : FCView, paint : FCPaint, clipRect : FCRect) {
	if (div.borderColor != null && div.borderColor != "none") {
		paint.drawRoundRect(div.borderColor, div.borderWidth, null, 0, 0, div.size.cx, div.size.cy, div.cornerRadius);
	}
}

let g_dragScrollView_Grid : FCGrid | null = null;//正在滚动的表格
let g_scrollAddSpeed_Grid : number = 0;//滚动加速
let g_scrollDirection_Grid : number = 0; //滚动方向

/*
 * 快速添加表格列
 * grid:表格
 * columns:列名集合
 */
function fastAddGridColumns(grid : FCGrid, columns : Array<string>) {
	let columnsSize = columns.length;
	for (let i = 0; i < columnsSize; i++) {
		let gridColumn = new FCGridColumn();
		gridColumn.text = columns[i];
		grid.columns.push(gridColumn);
	}
}

/*
 * 快速添加表格行
 * grid:表格
 * datas:数据集合
 */
function fastAddGridRow(grid : FCGrid, datas : Array<string>) : FCGridRow {
	let gridRow = new FCGridRow();
	let datasSize = datas.length;
	for (let i = 0; i < datasSize; i++) {
		let gridCell = new FCGridCell();
		gridCell.value = datas[i];
		gridRow.cells.push(gridCell);
	}
	return gridRow;
}

/*
 * 添加视图到单元格
 * view:视图
 * cell:单元格
 * grid:表格
 */
function addViewToGridCell(view : FCView, cell : FCGridCell, grid : FCGrid) {
	view.displayOffset = false;
	view.visible = false;
	cell.view = view;
	addViewToParent(view, grid);
}

/*
* 绘制单元格
* grid:表格
* row:行
* column:列
* cell:单元格
* paint:绘图对象
* left:左侧坐标
* top:上方坐标
* right:右侧坐标
* bottom:下方坐标
*/
function drawGridCell(grid : FCGrid, row : FCGridRow, column : FCGridColumn, cell : FCGridCell, paint : FCPaint, left : number, top : number, right : number, bottom : number) {
	if (cell.backColor != null && cell.backColor != "none") {
		paint.fillRect(cell.backColor, left, top, right, bottom);
	}
	if (row.selected) {
		if (grid.selectedRowColor != null && grid.selectedRowColor != "none") {
			paint.fillRect(grid.selectedRowColor, left, top, right, bottom);
		}
	}
	if (cell.borderColor != null && cell.borderColor != "none") {
		paint.drawRect(cell.borderColor, 1, null, left, top, right, bottom);
	}
	if (cell.value != null) {
		let showText = cell.value;
		if (column.colType == "double") {
			if (cell.digit >= 0) {
				let numValue = strToNumber(showText!);
				showText = numValue.toFixed(cell.digit);
			}
		}
		let tSize = paint.textSize(showText, cell.font);
		if (tSize.cx > column.width) {
			paint.drawTextAutoEllipsis(showText, cell.textColor, cell.font, left + 2, top + grid.rowHeight / 2 - tSize.cy / 2, left + 2 + column.width, top + grid.rowHeight / 2 - tSize.cy / 2);
		} else {
			if (column.cellAlign == "left") {
				paint.drawText(showText, cell.textColor, cell.font, left + 2, top + grid.rowHeight / 2 - tSize.cy / 2);
			} else if (column.cellAlign == "center") {
				paint.drawText(showText, cell.textColor, cell.font, left + (right - left - tSize.cx) / 2, top + grid.rowHeight / 2 - tSize.cy / 2);
			} else if (column.cellAlign == "right") {
				paint.drawText(showText, cell.textColor, cell.font, right - tSize.cx, top + grid.rowHeight / 2 - tSize.cy / 2);
			}
		}
	}
}

/*
* 绘制列
* grid:表格
* column:列
* paint:绘图对象
* left:左侧坐标
* top:上方坐标
* right:右侧坐标
* bottom:下方坐标
*/
function drawGridColumn(grid : FCGrid, column : FCGridColumn, paint : FCPaint, left : number, top : number, right : number, bottom : number) {
	let tSize = paint.textSize(column.text, column.font);
	if (column.backColor != null && column.backColor != "none") {
		paint.fillRect(column.backColor, left, top, right, bottom);
	}
	if (column.borderColor != null && column.borderColor != "none") {
		paint.drawRect(column.borderColor, 1, null, left, top, right, bottom);
	}
	paint.drawText(column.text, column.textColor, column.font, left + (column.width - tSize.cx) / 2, top + grid.headerHeight / 2 - tSize.cy / 2);
	if (column.sort == "asc") {
		paint.beginPath();
		let cR = (bottom - top) / 4;
		let oX = right - cR * 2, oY = top + (bottom - top) / 2;
		paint.addLine(oX, oY - cR, oX - cR, oY + cR);
		paint.addLine(oX - cR, oY + cR, oX + cR, oY + cR);
		paint.addLine(oX + cR, oY + cR, oX, oY - cR);
		paint.fillPath(column.textColor);
		paint.closePath();
	}
	else if (column.sort == "desc") {
		paint.beginPath();
		let cR = (bottom - top) / 4;
		let oX = right - cR * 2, oY = top + (bottom - top) / 2;
		paint.addLine(oX, oY + cR, oX - cR, oY - cR);
		paint.addLine(oX - cR, oY - cR, oX + cR, oY - cR);
		paint.addLine(oX + cR, oY - cR, oX, oY + cR);
		paint.fillPath(column.textColor);
		paint.closePath();
	}
}

/*
* 绘制表格
* grid:表格
* paint:绘图对象
* clipRect:裁剪区域
*/
function drawGrid(grid : FCGrid, paint : FCPaint, clipRect : FCRect) {
	let cTop = -grid.scrollV + grid.headerHeight;
	//绘制行
	let colLeft = 0;
	for (let i = 0; i < grid.views.length; i++) {
		grid.views[i].visible = false;
	}
	for (let i = 0; i < grid.columns.length; i++) {
		if (grid.columns[i].widthStr.length > 0) {
			let newWidthStr = grid.columns[i].widthStr.replace("%", "");
			grid.columns[i].width = strToNumber(newWidthStr) * grid.size.cx / 100;
		}
		let colRect = new FCRect(colLeft, 0, colLeft + grid.columns[i].width, grid.headerHeight);
		grid.columns[i].bounds = colRect;
		grid.columns[i].index = i;
		colLeft += grid.columns[i].width;
	}
	for (let i = 0; i < grid.rows.length; i++) {
		let row = grid.rows[i];
		row.index = i;
		if (row.visible) {
			let rTop = cTop, rBottom = cTop + grid.rowHeight;
			if (rBottom >= 0 && cTop <= grid.size.cy) {
				for (let j = 0; j < row.cells.length; j++) {
					let cell = row.cells[j];
					let gridColumn = cell.column;
					if (gridColumn == null) {
						gridColumn = grid.columns[j];
					}
					if (gridColumn.visible) {
						if (!gridColumn.frozen) {
							let cellWidth = gridColumn.width;
							let colSpan = cell.colSpan;
							if (colSpan > 1) {
								for (let n = 1; n < colSpan; n++) {
									let spanColumn = grid.columns[(gridColumn as FCGridColumn).index + n] as FCGridColumn;
									if (spanColumn != null && spanColumn.visible) {
										cellWidth += spanColumn.width;
									}
								}
							}
							let cellHeight = grid.rowHeight;
							let rowSpan = cell.rowSpan;
							if (rowSpan > 1) {
								for (let n = 1; n < rowSpan; n++) {
									let spanRow = grid.rows[i + n];
									if (spanRow != null && spanRow.visible) {
										cellHeight += grid.rowHeight;
									}
								}
							}
							let cRect = new FCRect(gridColumn.bounds.left - grid.scrollH, rTop, gridColumn.bounds.left + cellWidth - grid.scrollH, rTop + cellHeight);
							if (cRect.right >= 0 && cRect.left < grid.size.cx) {
								if (paint.onPaintGridCell != null) {
									paint.onPaintGridCell!(grid, row, gridColumn, cell, paint, cRect.left, cRect.top, cRect.right, cRect.bottom);
								} else {
									drawGridCell(grid, row, gridColumn, cell, paint, cRect.left, cRect.top, cRect.right, cRect.bottom);
								}
								if (cell.view != null) {
									cell.view!.visible = true;
									cell.view!.location = new FCPoint(cRect.left + grid.scrollH, cRect.top + grid.scrollV);
									cell.view!.size = new FCSize(cRect.right - cRect.left, cRect.bottom - cRect.top);
								}
							}
						}
					}
				}
			}
			if (rBottom >= 0 && cTop <= grid.size.cy) {
				for (let j = 0; j < row.cells.length; j++) {
					let cell = row.cells[j];
					let gridColumn = cell.column as FCGridColumn;
					if (gridColumn == null) {
						gridColumn = grid.columns[j];
					}
					if (gridColumn.visible) {
						if (gridColumn.frozen) {
							let cellWidth = gridColumn.width;
							let colSpan = cell.colSpan;
							if (colSpan > 1) {
								for (let n = 1; n < colSpan; n++) {
									let spanColumn = grid.columns[gridColumn.index + n];
									if (spanColumn != null && spanColumn.visible) {
										cellWidth += spanColumn.width;
									}
								}
							}
							let cellHeight = grid.rowHeight;
							let rowSpan = cell.rowSpan;
							if (rowSpan > 1) {
								for (let n = 1; n < rowSpan; n++) {
									let spanRow = grid.rows[i + n];
									if (spanRow != null && spanRow.visible) {
										cellHeight += grid.rowHeight;
									}
								}
							}
							let cRect = new FCRect(gridColumn.bounds.left, rTop, gridColumn.bounds.left + cellWidth, rTop + cellHeight);
							if (cRect.right >= 0 && cRect.left < grid.size.cx) {
								if (paint.onPaintGridCell != null) {
									paint.onPaintGridCell!(grid, row, gridColumn, cell, paint, cRect.left, cRect.top, cRect.right, cRect.bottom);
								} else {
									drawGridCell(grid, row, gridColumn, cell, paint, cRect.left, cRect.top, cRect.right, cRect.bottom);
								}
								if (cell.view != null) {
									cell.view!.visible = true;
									cell.view!.location = new FCPoint(cRect.left + grid.scrollH, cRect.top + grid.scrollV);
									cell.view!.size = new FCSize(cRect.right - cRect.left, cRect.bottom - cRect.top);
								}
							}
						}
					}
				}
			}
			if (cTop > grid.size.cy) {
				break;
			}
			cTop += grid.rowHeight;
		}
	}
}

/*
* 绘制表格的滚动条
* grid:表格
* paint:绘图对象
* clipRect:裁剪区域
*/
function drawGridScrollBar(grid : FCGrid, paint : FCPaint, clipRect : FCRect) {
	grid.hScrollIsVisible = false;
	grid.vScrollIsVisible = false;
	if (grid.headerHeight > 0) {
		let cLeft = -grid.scrollH;
		//绘制列
		for (let i = 0; i < grid.columns.length; i++) {
			let gridColumn = grid.columns[i];
			if (grid.columns[i].visible) {
				if (!gridColumn.frozen) {
					if (paint.onPaintGridColumn != null) {
						paint.onPaintGridColumn!(grid, grid.columns[i], paint, cLeft, 0, cLeft + gridColumn.width, grid.headerHeight);
					} else {
						drawGridColumn(grid, grid.columns[i], paint, cLeft, 0, cLeft + gridColumn.width, grid.headerHeight);
					}
				}
				cLeft += gridColumn.width;
			}
		}
		cLeft = 0;
		for (let i = 0; i < grid.columns.length; i++) {
			let gridColumn = grid.columns[i];
			if (grid.columns[i].visible) {
				if (gridColumn.frozen) {
					if (paint.onPaintGridColumn != null) {
						paint.onPaintGridColumn!(grid, grid.columns[i], paint, cLeft, 0, cLeft + gridColumn.width, grid.headerHeight);
					} else {
						drawGridColumn(grid, grid.columns[i], paint, cLeft, 0, cLeft + gridColumn.width, grid.headerHeight);
					}
				}
				cLeft += gridColumn.width;
			}
		}
	}
	if (paint.isMobile) {
		if (paint.touchDownView == grid) {
		} else if (g_dragScrollView_Grid == grid && g_scrollAddSpeed_Grid != 0) {
		} else {
			return;
		}
	}
	if (grid.showHScrollBar) {
		let contentWidth = getGridContentWidth(grid);
		if (contentWidth > 0 && contentWidth > grid.size.cx) {
			let sLeft = grid.scrollH / contentWidth * grid.size.cx;
			let sRight = (grid.scrollH + grid.size.cx) / contentWidth * grid.size.cx;
			if (sRight - sLeft < grid.scrollSize) {
				sRight = sLeft + grid.scrollSize;
			}
			if (paint.touchMoveView == grid && (grid.hoverScrollHButton || grid.downScrollHButton)) {
				paint.fillRect(grid.scrollBarHoveredColor, sLeft, grid.size.cy - grid.scrollSize, sRight, grid.size.cy);
			} else {
				paint.fillRect(grid.scrollBarColor, sLeft, grid.size.cy - grid.scrollSize, sRight, grid.size.cy);
			}
			grid.hScrollIsVisible = true;
		}
	}
	if (grid.showVScrollBar) {
		let contentHeight = getGridContentHeight(grid);
		if (contentHeight > 0 && contentHeight > grid.size.cy - grid.headerHeight) {
			let sTop = grid.headerHeight + grid.scrollV / contentHeight * (grid.size.cy - grid.headerHeight - grid.scrollSize);
			let sBottom = sTop + ((grid.size.cy - grid.headerHeight - grid.scrollSize)) / contentHeight * (grid.size.cy - grid.headerHeight - grid.scrollSize);
			if (sBottom - sTop < grid.scrollSize) {
				sBottom = sTop + grid.scrollSize;
			}
			if (paint.touchMoveView == grid && (grid.hoverScrollVButton || grid.downScrollVButton)) {
				paint.fillRect(grid.scrollBarHoveredColor, grid.size.cx - grid.scrollSize, sTop, grid.size.cx, sBottom);
			} else {
				paint.fillRect(grid.scrollBarColor, grid.size.cx - grid.scrollSize, sTop, grid.size.cx, sBottom);
			}
			grid.vScrollIsVisible = true;
		}
	}
}

/*
* 获取内容的宽度
* grid:表格
*/
function getGridContentWidth(grid : FCGrid) : number {
	let cWidth = 0;
	for (let i = 0; i < grid.columns.length; i++) {
		if (grid.columns[i].visible) {
			cWidth += grid.columns[i].width;
		}
	}
	return cWidth;
}

/*
* 获取内容的高度
* grid:表格
*/
function getGridContentHeight(grid : FCGrid) : number {
	let cHeight = 0;
	for (let i = 0; i < grid.rows.length; i++) {
		if (grid.rows[i].visible) {
			cHeight += grid.rowHeight;
		}
	}
	return cHeight;
}

/*
* 表格的鼠标移动方法
* grid: 表格
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
*/
function touchMoveGrid(grid : FCGrid, firstTouch : boolean, firstPoint : FCPoint, secondTouch : boolean, secondPoint : FCPoint) {
	grid.hoverScrollHButton = false;
	grid.hoverScrollVButton = false;
	let mp = firstPoint;
	if (firstTouch) {
		if (grid.paint!.resizeColumnState != 0) {
			let gridColumn = grid.columns[grid.paint!.resizeColumnIndex];
			let newWidth = grid.paint!.resizeColumnBeginWidth + (mp.x - grid.startPoint.x);
			if (newWidth > 10) {
				gridColumn.width = newWidth;
			}
			return;
		}
		if (grid.showHScrollBar || grid.showVScrollBar) {
			if (grid.downScrollHButton) {
				let contentWidth = getGridContentWidth(grid);
				let subX = (mp.x - grid.startPoint.x) / grid.size.cx * contentWidth;
				let newScrollH = grid.startScrollH + subX;
				if (newScrollH < 0) {
					newScrollH = 0;
				} else if (newScrollH > contentWidth - grid.size.cx) {
					newScrollH = contentWidth - grid.size.cx;
				}
				grid.scrollH = newScrollH;
				grid.paint!.cancelClick = true;
				return;

			} else if (grid.downScrollVButton) {
				let contentHeight = getGridContentHeight(grid);
				let subY = (mp.y - grid.startPoint.y) / (grid.size.cy - grid.headerHeight - grid.scrollSize) * contentHeight;
				let newScrollV = grid.startScrollV + subY;
				if (newScrollV < 0) {
					newScrollV = 0;
				} else if (newScrollV > contentHeight - (grid.size.cy - grid.headerHeight - grid.scrollSize)) {
					newScrollV = contentHeight - (grid.size.cy - grid.headerHeight - grid.scrollSize);
				}
				grid.scrollV = newScrollV;
				grid.paint!.cancelClick = true;
				return;
			}
		}
		if (grid.allowDragScroll) {
			let contentWidth = getGridContentWidth(grid);
			if (contentWidth > grid.size.cx - grid.scrollSize) {
				let subX = grid.startPoint.x - mp.x;
				let newScrollH = grid.startScrollH + subX;
				if (newScrollH < 0) {
					newScrollH = 0;
				} else if (newScrollH > contentWidth - grid.size.cx) {
					newScrollH = contentWidth - grid.size.cx;
				}
				grid.scrollH = newScrollH;
				if (Math.abs(subX) > 5) {
					grid.paint!.cancelClick = true;
				}
			}
			let contentHeight = getGridContentHeight(grid);
			if (contentHeight > grid.size.cy - grid.headerHeight - grid.scrollSize) {
				let subY = grid.startPoint.y - mp.y;
				let newScrollV = grid.startScrollV + subY;
				if (newScrollV < 0) {
					newScrollV = 0;
				} else if (newScrollV > contentHeight - (grid.size.cy - grid.headerHeight - grid.scrollSize)) {
					newScrollV = contentHeight - (grid.size.cy - grid.headerHeight - grid.scrollSize);
				}
				grid.scrollV = newScrollV;
				if (Math.abs(subY) > 5) {
					grid.paint!.cancelClick = true;
				}
			}
		}
	} else {
		if (grid.showHScrollBar) {
			let contentWidth = getGridContentWidth(grid);
			if (contentWidth > 0 && contentWidth > grid.size.cx - grid.scrollSize) {
				let sLeft = grid.scrollH / contentWidth * grid.size.cx;
				let sRight = (grid.scrollH + grid.size.cx) / contentWidth * grid.size.cx;
				if (sRight - sLeft < grid.scrollSize) {
					sRight = sLeft + grid.scrollSize;
				}
				if (mp.x >= sLeft && mp.x <= sRight && mp.y >= grid.size.cy - grid.scrollSize && mp.y <= grid.size.cy) {
					grid.hoverScrollHButton = true;
					return;
				} else {
					grid.hoverScrollHButton = false;
				}
			}
		}
		if (grid.showVScrollBar) {
			let contentHeight = getGridContentHeight(grid);
			if (contentHeight > 0 && contentHeight > grid.size.cy - grid.headerHeight - grid.scrollSize) {
				let sTop = grid.headerHeight + grid.scrollV / contentHeight * (grid.size.cy - grid.headerHeight - grid.scrollSize);
				let sBottom = grid.headerHeight + (grid.scrollV + (grid.size.cy - grid.headerHeight - grid.scrollSize)) / contentHeight * (grid.size.cy - grid.headerHeight - grid.scrollSize);
				if (sBottom - sTop < grid.scrollSize) {
					sBottom = sTop + grid.scrollSize;
				}
				if (mp.x >= grid.size.cx - grid.scrollSize && mp.x <= grid.size.cx && mp.y >= sTop && mp.y <= sBottom) {
					grid.hoverScrollVButton = true;
					return;
				} else {
					grid.hoverScrollVButton = false;
				}
			}
		}
	}
}

/*
* 表格的鼠标按下方法
* grid: 表格
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
* clicks:点击次数
*/
function touchDownGrid(grid : FCGrid, firstTouch : boolean, firstPoint : FCPoint, secondTouch : boolean, secondPoint : FCPoint, clicks : number) {
	let mp = firstPoint;
	grid.touchDownTime = new Date().getTime()
	grid.startPoint = mp;
	grid.downScrollHButton = false;
	grid.downScrollVButton = false;
	grid.hoverScrollHButton = false;
	grid.hoverScrollVButton = false;
	g_dragScrollView_Grid = null;
	g_scrollAddSpeed_Grid = 0;
	g_scrollDirection_Grid = 0;
	if (grid.showHScrollBar) {
		let contentWidth = getGridContentWidth(grid);
		if (contentWidth > 0 && contentWidth > grid.size.cx - grid.scrollSize) {
			let sLeft = grid.scrollH / contentWidth * grid.size.cx;
			let sRight = (grid.scrollH + grid.size.cx) / contentWidth * grid.size.cx;
			if (sRight - sLeft < grid.scrollSize) {
				sRight = sLeft + grid.scrollSize;
			}
			if (mp.x >= sLeft && mp.x <= sRight && mp.y >= grid.size.cy - grid.scrollSize && mp.y <= grid.size.cy) {
				grid.downScrollHButton = true;
				grid.startScrollH = grid.scrollH;
				return;
			}
		}
	}
	if (grid.showVScrollBar) {
		let contentHeight = getGridContentHeight(grid);
		if (contentHeight > 0 && contentHeight > grid.size.cy - grid.headerHeight - grid.scrollSize) {
			let sTop = grid.headerHeight + grid.scrollV / contentHeight * (grid.size.cy - grid.headerHeight - grid.scrollSize);
			let sBottom = grid.headerHeight + (grid.scrollV + (grid.size.cy - grid.headerHeight - grid.scrollSize)) / contentHeight * (grid.size.cy - grid.headerHeight - grid.scrollSize);
			if (sBottom - sTop < grid.scrollSize) {
				sBottom = sTop + grid.scrollSize;
			}
			if (mp.x >= grid.size.cx - grid.scrollSize && mp.x <= grid.size.cx && mp.y >= sTop && mp.y <= sBottom) {
				grid.downScrollVButton = true;
				grid.startScrollV = grid.scrollV;
				return;
			}
		}
	}
	if (grid.allowDragScroll) {
		grid.startScrollH = grid.scrollH;
		grid.startScrollV = grid.scrollV;
	}
	let colLeft = 0;
	for (let i = 0; i < grid.columns.length; i++) {
		let colRect = new FCRect(colLeft, 0, colLeft + grid.columns[i].width, grid.headerHeight);
		grid.columns[i].bounds = colRect;
		grid.columns[i].index = i;
		colLeft += grid.columns[i].width;
	}
	grid.paint!.resizeColumnState = 0;
	grid.paint!.resizeColumnBeginWidth = 0;
	if (grid.headerHeight > 0 && mp.y <= grid.headerHeight) {
		//绘制列
		for (let i = 0; i < grid.columns.length; i++) {
			let gridColumn = grid.columns[i];
			if (gridColumn.visible) {
				let bounds = gridColumn.bounds;
				if (mp.x >= bounds.left - grid.scrollH && mp.x <= bounds.right - grid.scrollH) {
					if (gridColumn.index > 0 && mp.x < bounds.left + 5 - grid.scrollH) {
						grid.paint!.resizeColumnState = 1;
						grid.paint!.resizeColumnBeginWidth = grid.columns[gridColumn.index - 1].bounds.right - grid.columns[gridColumn.index - 1].bounds.left;
						grid.paint!.resizeColumnIndex = gridColumn.index - 1;
						return;
					}
					else if (mp.x > bounds.right - 5 - grid.scrollH) {
						grid.paint!.resizeColumnState = 2;
						grid.paint!.resizeColumnBeginWidth = bounds.right - bounds.left;
						grid.paint!.resizeColumnIndex = gridColumn.index;
						return;
					}
					break;
				}
			}
		}
	}
	
	let cTop = -grid.scrollV + grid.headerHeight;
	//绘制行
	colLeft = 0;
	for (let i = 0; i < grid.columns.length; i++) {
		let colRect = new FCRect(colLeft, 0, colLeft + grid.columns[i].width, grid.headerHeight);
		grid.columns[i].bounds = colRect;
		grid.columns[i].index = i;
		colLeft += grid.columns[i].width;
	}
	if (grid.headerHeight > 0 && firstPoint.y <= grid.headerHeight) {
		let cLeft = 0;
		//绘制列
		for (let i = 0; i < grid.columns.length; i++) {
			let gridColumn = grid.columns[i];
			if (grid.columns[i].visible) {
				if (gridColumn.frozen) {
					if (firstPoint.x >= cLeft && firstPoint.x <= cLeft + gridColumn.width) {
						for (let j = 0; j < grid.columns.length; j++) {
							let tColumn = grid.columns[j];
							if (tColumn == gridColumn) {
								if (tColumn.allowSort) {
									if (tColumn.sort == "none" || tColumn.sort == "desc") {
										tColumn.sort = "asc";
										/*grid.rows.sort((m, n) => {
											if (m.cells.length > j && n.cells.length > j) {
												if (m.cells[j].value < n.cells[j].value) {
													return -1;
												}
												else if (m.cells[j].value > n.cells[j].value) {
													return 1;
												}
												else return 0;
											}
											else {
												return 0;
											}
										});*/
									} else {
										tColumn.sort = "desc";
										/*grid.rows.sort((m, n) => {
											if (m.cells.length > j && n.cells.length > j) {
												if (m.cells[j].value > n.cells[j].value) {
													return -1;
												}
												else if (m.cells[j].value < n.cells[j].value) {
													return 1;
												}
												else return 0;
											} else {
												return 0;
											}
										});*/
									}
								} else {
									tColumn.sort = "none";
								}
							} else {
								tColumn.sort = "none";
							}
						}
						if (grid.paint != null && grid.paint!.onClickGridColumn != null) {
							grid.paint!.onClickGridColumn!(grid, gridColumn, firstTouch, firstPoint, secondTouch, secondPoint, clicks);
						}
						return;
					}
				}
				cLeft += gridColumn.width;
			}
		}
		cLeft = -grid.scrollH;
		for (let i = 0; i < grid.columns.length; i++) {
			let gridColumn = grid.columns[i];
			if (grid.columns[i].visible) {
				if (!gridColumn.frozen) {
					if (firstPoint.x >= cLeft && firstPoint.x <= cLeft + gridColumn.width) {
						for (let j = 0; j < grid.columns.length; j++) {
							let tColumn = grid.columns[j];
							if (tColumn == gridColumn) {
								if (tColumn.allowSort) {
									if (tColumn.sort == "none" || tColumn.sort == "desc") {
										tColumn.sort = "asc";
										/*grid.rows.sort((m, n) => {
											if (m.cells.length > j && n.cells.length > j) {
												if (m.cells[j].value < n.cells[j].value) {
													return -1;
												}
												else if (m.cells[j].value > n.cells[j].value) {
													return 1;
												}
												else return 0;
											} else {
												return 0;
											}
										});*/
									} else {
										tColumn.sort = "desc";
										/*grid.rows.sort((m, n) => {
											if (m.cells.length > j && n.cells.length > j) {
												if (m.cells[j].value > n.cells[j].value) {
													return -1;
												}
												else if (m.cells[j].value < n.cells[j].value) {
													return 1;
												}
												else return 0;
											} else {
												return 0;
											}
										});*/
									}
								} else {
									tColumn.sort = "none";
								}
							} else {
								tColumn.sort = "none";
							}
						}
						if (grid.paint != null && grid.paint!.onClickGridColumn != null) {
							grid.paint!.onClickGridColumn!(grid, gridColumn, firstTouch, firstPoint, secondTouch, secondPoint, clicks);
						}
						return;
					}
				}
				cLeft += gridColumn.width;
			}
		}
	}
	for (let i = 0; i < grid.rows.length; i++) {
		let row = grid.rows[i];
		if (row.visible) {
			let rTop = cTop, rBottom = cTop + grid.rowHeight;
			if (rBottom >= 0 && cTop <= grid.size.cy) {
				for (let j = 0; j < row.cells.length; j++) {
					let cell = row.cells[j];
					let gridColumn = cell.column as FCGridColumn;
					if (gridColumn == null) {
						gridColumn = grid.columns[j];
					}
					if (gridColumn.visible) {
						if (gridColumn.frozen) {
							let cellWidth = gridColumn.width;
							let colSpan = cell.colSpan;
							if (colSpan > 1) {
								for (let n = 1; n < colSpan; n++) {
									let spanColumn = grid.columns[gridColumn.index + n] as FCGridColumn;
									if (spanColumn != null && spanColumn.visible) {
										cellWidth += spanColumn.width;
									}
								}
							}
							let cellHeight = grid.rowHeight;
							let rowSpan = cell.rowSpan;
							if (rowSpan > 1) {
								for (let n = 1; n < rowSpan; n++) {
									let spanRow = grid.rows[i + n];
									if (spanRow != null && spanRow.visible) {
										cellHeight += grid.rowHeight;
									}
								}
							}

							let cRect = new FCRect(gridColumn.bounds.left, rTop, gridColumn.bounds.left + cellWidth, rTop + cellHeight);
							if (cRect.right >= 0 && cRect.left < grid.size.cx) {
								if (firstPoint.x >= cRect.left && firstPoint.x <= cRect.right && firstPoint.y >= cRect.top && firstPoint.y <= cRect.bottom) {
									for (let r = 0; r < grid.rows.length; r++) {
										let subRow = grid.rows[r];
										if (subRow == row) {
											subRow.selected = true;
										} else {
											subRow.selected = false;
										}
									}
									if (grid.paint != null && grid.paint!.onClickGridCell != null) {
										grid.paint!.onClickGridCell!(grid, row, gridColumn, cell, firstTouch, firstPoint, secondTouch, secondPoint, clicks);
									}
									return;
								}
							}
						}
					}
				}
			}
			if (rBottom >= 0 && cTop <= grid.size.cy) {
				for (let j = 0; j < row.cells.length; j++) {
					let cell = row.cells[j];
					let gridColumn = cell.column as FCGridColumn;
					if (gridColumn == null) {
						gridColumn = grid.columns[j];
					}
					if (gridColumn.visible) {
						if (!gridColumn.frozen) {
							let cellWidth = gridColumn.width;
							let colSpan = cell.colSpan;
							if (colSpan > 1) {
								for (let n = 1; n < colSpan; n++) {
									let spanColumn = grid.columns[gridColumn.index + n] as FCGridColumn;
									if (spanColumn != null && spanColumn.visible) {
										cellWidth += spanColumn.width;
									}
								}
							}
							let cellHeight = grid.rowHeight;
							let rowSpan = cell.rowSpan;
							if (rowSpan > 1) {
								for (let n = 1; n < rowSpan; n++) {
									let spanRow = grid.rows[i + n];
									if (spanRow != null && spanRow.visible) {
										cellHeight += grid.rowHeight;
									}
								}
							}
							let cRect = new FCRect(gridColumn.bounds.left - grid.scrollH, rTop, gridColumn.bounds.left + cellWidth - grid.scrollH, rTop + cellHeight);
							if (cRect.right >= 0 && cRect.left < grid.size.cx) {
								if (firstPoint.x >= cRect.left && firstPoint.x <= cRect.right && firstPoint.y >= cRect.top && firstPoint.y <= cRect.bottom) {
									for (let r = 0; r < grid.rows.length; r++) {
										let subRow = grid.rows[r];
										if (subRow == row) {
											subRow.selected = true;
										} else {
											subRow.selected = false;
										}
									}
									if (grid.paint != null && grid.paint!.onClickGridCell != null) {
										grid.paint!.onClickGridCell!(grid, row, gridColumn, cell, firstTouch, firstPoint, secondTouch, secondPoint, clicks);
									}
									return;
								}
							}
						}
					}
				}
			}
			if (cTop > grid.size.cy) {
				break;
			}
			cTop += grid.rowHeight;
		}
	}
}

/*
* 表格的鼠标抬起方法
* grid: 表格
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
* clicks:点击次数
*/
function touchUpGrid(grid : FCGrid, firstTouch : boolean, firstPoint : FCPoint, secondTouch : boolean, secondPoint : FCPoint, clicks : number) {
	if (grid.paint!.resizeColumnState != 0) {
		grid.paint!.resizeColumnState = 0;
		return;
	}
	grid.hoverScrollHButton = false;
	grid.hoverScrollVButton = false;
	if (firstTouch && !grid.downScrollHButton && !grid.downScrollVButton) {
		if (grid.allowDragScroll) {
			let touchUpTime = new Date().getTime();
			let diff = touchUpTime - grid.touchDownTime;
			//加速滚动
			if (diff < 250) {
				let sub1 = 100 * ((Math.abs(firstPoint.y - grid.startPoint.y)) / 20) / diff * 10;
				let sub2 = 100 * ((Math.abs(firstPoint.x - grid.startPoint.x)) / 20) / diff * 10;
				if ("A:" + sub1 != "A:NaN" && "A:" + sub2 != "A:NaN") {
					if (Math.abs(sub1) > Math.abs(sub2)) {
						if (firstPoint.y < grid.startPoint.y) {
							g_scrollAddSpeed_Grid += sub1;
						} else {
							g_scrollAddSpeed_Grid -= sub1;
						}
						g_scrollDirection_Grid = 0;
					} else {
						if (firstPoint.x < grid.startPoint.x) {
							g_scrollAddSpeed_Grid += sub2;
						} else {
							g_scrollAddSpeed_Grid -= sub2;
						}
						g_scrollDirection_Grid = 1;
					}
					if (Math.abs(g_scrollAddSpeed_Grid) > 0) {
						grid.paint!.cancelClick = true;
					}
					g_dragScrollView_Grid = grid;
				}
			}
		}
	}
	grid.downScrollHButton = false;
	grid.downScrollVButton = false;
}

/*
* 检查拖动滚动
*/
function checkGridDragScroll() {
	if (g_dragScrollView_Grid) {
		let sub = Math.floor(g_scrollAddSpeed_Grid / 10);
		if (sub == 0 && g_scrollAddSpeed_Grid > 1) {
			sub = 1;
		} else if (sub == 0 && g_scrollAddSpeed_Grid < -1) {
			sub = -1;
		}
		g_scrollAddSpeed_Grid -= sub;
		if (sub == 0) {
			let viewCache = g_dragScrollView_Grid as FCGrid;
			g_dragScrollView_Grid = null as any;
			g_scrollAddSpeed_Grid = 0;
			if (viewCache.paint != null) {
				invalidateView(viewCache);
			}
		} else {
			let viewCache = g_dragScrollView_Grid as FCGrid;
			let oldScrollV = Math.floor(viewCache.scrollV + g_scrollAddSpeed_Grid);
			let oldScrollH = Math.floor(viewCache.scrollH + g_scrollAddSpeed_Grid);
			if (g_scrollDirection_Grid == 0) {
				let contentHeight = getGridContentHeight(viewCache);
				if (contentHeight < viewCache.size.cy - viewCache.scrollSize) {
					viewCache.scrollV = 0;
				} else {
					if (oldScrollV < 0) {
						oldScrollV = 0;
					} else if (oldScrollV > contentHeight - viewCache.size.cy + viewCache.headerHeight + viewCache.scrollSize) {
						oldScrollV = contentHeight - viewCache.size.cy + viewCache.headerHeight + viewCache.scrollSize;
					}
					viewCache.scrollV = oldScrollV;
				}
			} else {
				let contentWidth = getGridContentWidth(viewCache);
				if (contentWidth < viewCache.size.cx - viewCache.headerHeight - viewCache.scrollSize) {
					viewCache.scrollH = 0;
				} else {
					if (oldScrollH < 0) {
						oldScrollH = 0;
					} else if (oldScrollH > contentWidth - viewCache.size.cx) {
						oldScrollH = contentWidth - viewCache.size.cx;
					}
					viewCache.scrollH = oldScrollH;
				}
			}
			if (viewCache.paint != null) {
				invalidateView(viewCache);
			}
		}
	}
}

/*
* 表格的鼠标滚轮方法
* grid:表格
* delta:滚轮值
*/
function touchWheelGrid(grid : FCGrid, delta : number) {
	let oldScrollV = grid.scrollV;
	if (delta < 0) {
		oldScrollV -= grid.rowHeight;
	} else if (delta > 0) {
		oldScrollV += grid.rowHeight;
	}
	let contentHeight = getGridContentHeight(grid);
	if (contentHeight < grid.size.cy - grid.headerHeight - grid.scrollSize) {
		grid.scrollV = 0;
	} else {
		if (oldScrollV < 0) {
			oldScrollV = 0;
		} else if (oldScrollV > contentHeight - grid.size.cy + grid.headerHeight + grid.scrollSize) {
			oldScrollV = contentHeight - grid.size.cy + grid.headerHeight + grid.scrollSize;
		}
		grid.scrollV = oldScrollV;
	}
}

/*
* 重置布局图层
* layout:布局层
*/
function resetLayoutDiv(layout : FCLayoutDiv) : boolean {
	let reset = false;
	let padding = layout.padding;
	let vPos = 0, left = padding.left, top = padding.top, width = layout.size.cx - padding.left - padding.right, height = layout.size.cy - padding.top - padding.bottom;
	for (let i = 0; i < layout.views.length; i++) {
		let view = layout.views[i];
		if (view.visible) {
			let size = view.size;
			let margin = view.margin;
			let cLeft = view.location.x, cTop = view.location.y, cWidth = size.cx, cHeight = size.cy;
			let nLeft = cLeft, nTop = cTop, nWidth = cWidth, nHeight = cHeight;
			if (layout.layoutStyle == "bottomtotop") {
				if (i == 0) {
					top = height - padding.top;
				}
				let lWidth = 0;
				if (layout.autoWrap) {
					lWidth = size.cx;
					let lTop = top - margin.top - cHeight - margin.bottom;
					if (lTop < padding.top) {
						if (vPos != 0) {
							left += cWidth + margin.left;
						}
						top = height - padding.top;
					}
				}
				else {
					lWidth = width - margin.left - margin.right;
				}
				top -= cHeight + margin.bottom;
				nLeft = left + margin.left;
				nWidth = lWidth;
				nTop = top;
			} else if (layout.layoutStyle == "lefttoright") {
				let lHeight = 0;
				if (layout.autoWrap) {
					lHeight = size.cy;
					let lRight = left + margin.left + cWidth + margin.right;
					if (lRight > width) {
						left = padding.left;
						if (vPos != 0) {
							top += cHeight + margin.top;
						}
					}
				}
				else {
					lHeight = height - margin.top - margin.bottom;
				}
				left += margin.left;
				nLeft = left;
				nTop = top + margin.top;
				nHeight = lHeight;
				left += cWidth + margin.right;
			} else if (layout.layoutStyle == "righttoleft") {
				if (i == 0) {
					left = width - padding.left;
				}
				let lHeight = 0;
				if (layout.autoWrap) {
					lHeight = size.cy;
					let lLeft = left - margin.left - cWidth - margin.right;
					if (lLeft < padding.left) {
						left = width - padding.left;
						if (vPos != 0) {
							top += cHeight + margin.top;
						}
					}
				}
				else {
					lHeight = height - margin.top - margin.bottom;
				}
				left -= cWidth + margin.left;
				nLeft = left;
				nTop = top + margin.top;
				nHeight = lHeight;
			} else if (layout.layoutStyle == "toptobottom") {
				let lWidth = 0;
				if (layout.autoWrap) {
					lWidth = size.cx;
					let lBottom = top + margin.top + cHeight + margin.bottom;
					if (lBottom > height) {
						if (vPos != 0) {
							left += cWidth + margin.left + margin.right;
						}
						top = padding.top;
					}
				}
				else {
					lWidth = width - margin.left - margin.right;
				}
				top += margin.top;
				nTop = top;
				nLeft = left + margin.left;
				nWidth = lWidth;
				top += cHeight + margin.bottom;
			}
			if (cLeft != nLeft || cTop != nTop || cWidth != nWidth || cHeight != nHeight) {
				view.location = new FCPoint(nLeft, nTop);
				view.size = new FCSize(nWidth, nHeight);
				reset = true;
			}
			vPos++;
		}
	}
	return reset;
}

/*
* 更新页的布局
* tabView:多页夹
* tabPage:页
* left:左侧坐标
* top:上方坐标
* width:宽度
* height:高度
* tw:页头按钮的宽度
* th:页头按钮的高度
*/
function updataPageLayout(tabView : FCTabView, tabPage : FCTabPage, left : number, top : number, width : number, height : number, tw : number, th : number) {
	let newBounds = new FCRect(0, 0, 0, 0);
	if (tabView.layout == "bottom") {
		newBounds.left = 0;
		newBounds.top = 0;
		newBounds.right = width;
		newBounds.bottom = height - th;
		tabPage.headerButton!.location = new FCPoint(left, height - th);
	} else if (tabView.layout == "left") {
		newBounds.left = tw;
		newBounds.top = 0;
		newBounds.right = width;
		newBounds.bottom = height;
		tabPage.headerButton!.location = new FCPoint(0, top);
	} else if (tabView.layout == "right") {
		newBounds.left = 0;
		newBounds.top = 0;
		newBounds.right = width - tw;
		newBounds.bottom = height;
		tabPage.headerButton!.location = new FCPoint(width - tw, top);
	} else if (tabView.layout == "top") {
		newBounds.left = 0;
		newBounds.top = th;
		newBounds.right = width;
		newBounds.bottom = height;
		tabPage.headerButton!.location = new FCPoint(left, 0);
	}
	tabPage.location = new FCPoint(newBounds.left, newBounds.top);
	tabPage.size = new FCSize(newBounds.right - newBounds.left, newBounds.bottom - newBounds.top);
}

/*
* 更新多页夹的布局
* tabView:多页夹
*/
function updateTabLayout(tabView : FCTabView) {
	let width = tabView.size.cx;
	let height = tabView.size.cy;
	let left = 0, top = 0;
	for (let i = 0; i < tabView.tabPages.length; i++) {
		let tabPage = tabView.tabPages[i];
		let headerButton = tabView.tabPages[i].headerButton as FCView;
		if (headerButton.visible) {
			let tw = headerButton.size.cx;
			let th = headerButton.size.cy;
			updataPageLayout(tabView, tabPage, left, top, width, height, tw, th);
			left += tw;
			top += th;
		} else {
			tabPage.visible = false;
		}
	}
}

/*
* 重置分割线的布局
* split:分割视图
*/
function resetSplitLayoutDiv(split : FCSplitLayoutDiv) : boolean {
	let reset = false;
	let splitRect = new FCRect(0, 0, 0, 0);
	let width = split.size.cx, height = split.size.cy;
	let fRect = new FCRect(0, 0, 0, 0);
	let sRect = new FCRect(0, 0, 0, 0);
	let splitterSize = new FCSize(0, 0);
	if (split.splitter!.visible) {
		splitterSize.cx = split.splitter!.size.cx;
		splitterSize.cy = split.splitter!.size.cy;
	}
	let layoutStyle = split.layoutStyle;
	if (layoutStyle == "bottomtotop") {
		if (split.splitMode == "absolutesize" || split.oldSize.cy == 0) {
			splitRect.left = 0;
			splitRect.top = height - (split.oldSize.cy - split.splitter!.location.y);
			splitRect.right = width;
			splitRect.bottom = splitRect.top + splitterSize.cy;
		}
		else if (split.splitMode == "percentsize") {
			splitRect.left = 0;
			if (split.splitPercent == -1) {
				split.splitPercent = split.splitter!.location.y / split.oldSize.cy;
			}
			splitRect.top = height * split.splitPercent;
			splitRect.right = width;
			splitRect.bottom = splitRect.top + splitterSize.cy;
		}
		fRect.left = 0;
		fRect.top = splitRect.bottom;
		fRect.right = width;
		fRect.bottom = height;
		sRect.left = 0;
		sRect.top = 0;
		sRect.right = width;
		sRect.bottom = splitRect.top;
	}
	else if (layoutStyle == "lefttoright") {
		if (split.splitMode == "absolutesize" || split.oldSize.cx == 0) {
			splitRect.left = split.splitter!.location.x;
			splitRect.top = 0;
			splitRect.right = splitRect.left + splitterSize.cx;
			splitRect.bottom = height;
		}
		else if (split.splitMode == "percentsize") {
			if (split.splitPercent == -1) {
				split.splitPercent = split.splitter!.location.x / split.oldSize.cx;
			}
			splitRect.left = width * split.splitPercent;
			splitRect.top = 0;
			splitRect.right = splitRect.left + splitterSize.cx;
			splitRect.bottom = height;
		}
		fRect.left = 0;
		fRect.top = 0;
		fRect.right = splitRect.left;
		fRect.bottom = height;
		sRect.left = splitRect.right;
		sRect.top = 0;
		sRect.right = width;
		sRect.bottom = height;
	}
	else if (layoutStyle == "righttoleft") {
		if (split.splitMode == "absolutesize" || split.oldSize.cx == 0) {
			splitRect.left = width - (split.oldSize.cx - split.splitter!.location.x);
			splitRect.top = 0;
			splitRect.right = splitRect.left + splitterSize.cx;
			splitRect.bottom = height;
		}
		else if (split.splitMode == "percentsize") {
			if (split.splitPercent == -1) {
				split.splitPercent = split.splitter!.location.x / split.oldSize.cx;
			}
			splitRect.left = width * split.splitPercent;
			splitRect.top = 0;
			splitRect.right = splitRect.left + splitterSize.cx;
			splitRect.bottom = height;
		}
		fRect.left = splitRect.right;
		fRect.top = 0;
		fRect.right = width;
		fRect.bottom = height;
		sRect.left = 0;
		sRect.top = 0;
		sRect.right = splitRect.left;
		sRect.bottom = height;
	}
	else if (layoutStyle == "toptobottom") {
		if (split.splitMode == "absolutesize" || split.oldSize.cy == 0) {
			splitRect.left = 0;
			splitRect.top = split.splitter!.location.y;
			splitRect.right = width;
			splitRect.bottom = splitRect.top + splitterSize.cy;
		}
		else if (split.splitMode == "percentsize") {
			splitRect.left = 0;
			if (split.splitPercent == -1) {
				split.splitPercent = split.splitter!.location.y / split.oldSize.cy;
			}
			splitRect.top = height * split.splitPercent;
			splitRect.right = width;
			splitRect.bottom = splitRect.top + splitterSize.cy;
		}
		fRect.left = 0;
		fRect.top = 0;
		fRect.right = width;
		fRect.bottom = splitRect.top;
		sRect.left = 0;
		sRect.top = splitRect.bottom;
		sRect.right = width;
		sRect.bottom = height;
	}
	if (split.splitter!.visible) {
		let spRect = new FCRect(split.splitter!.location.x, split.splitter!.location.y, split.splitter!.location.x + split.splitter!.size.cx, split.splitter!.location.y + split.splitter!.size.cy);
		if (spRect.left != splitRect.left || spRect.top != splitRect.top || spRect.right != splitRect.right || spRect.bottom != splitRect.bottom) {
			split.splitter!.location = new FCPoint(splitRect.left, splitRect.top);
			split.splitter!.size = new FCSize(splitRect.right - splitRect.left, splitRect.bottom - splitRect.top);
			reset = true;
		}
	}
	let fcRect = new FCRect(split.firstView!.location.x, split.firstView!.location.y, split.firstView!.location.x + split.firstView!.size.cx, split.firstView!.location.y + split.firstView!.size.cy);
	if (fcRect.left != fRect.left || fcRect.top != fRect.top || fcRect.right != fRect.right || fcRect.bottom != fRect.bottom) {
		reset = true;
		split.firstView!.location = new FCPoint(fRect.left, fRect.top);
		split.firstView!.size = new FCSize(fRect.right - fRect.left, fRect.bottom - fRect.top);
	}
	let scRect = new FCRect(split.secondView!.location.x, split.secondView!.location.y, split.secondView!.location.x + split.secondView!.size.cx, split.secondView!.location.y + split.secondView!.size.cy);
	if (scRect.left != sRect.left || scRect.top != sRect.top || scRect.right != sRect.right || scRect.bottom != sRect.bottom) {
		reset = true;
		split.secondView!.location = new FCPoint(sRect.left, sRect.top);
		split.secondView!.size = new FCSize(sRect.right - sRect.left, sRect.bottom - sRect.top);
	}
	split.oldSize = new FCSize(width, height);
	return reset;
}

/*
* 添加页
* tabView:多页夹
* tabPage:页
* tabButton:页头按钮
*/
function addTabPage(tabView : FCTabView, tabPage : FCTabPage, tabButton : FCView) {
	tabPage.headerButton = tabButton;
	tabPage.parent = tabView;
	tabPage.paint = tabView.paint;
	tabButton.parent = tabView;
	tabButton.paint = tabView.paint;
	tabView.tabPages.push(tabPage);
	tabView.views.push(tabPage);
	tabView.views.push(tabButton);
}


/*
* 移除页
* tabView:多页夹
* tabPage:页
*/
function removeTabPage(tabView : FCTabView, tabPage : FCTabPage) {
	let headerButton = tabPage.headerButton;
	for (let i = 0; i < tabView.views.length; i++) {
		if (tabView.views[i] == headerButton) {
			tabView.views.splice(i, 1);
			break;
		}
	}
	for (let i = 0; i < tabView.views.length; i++) {
		if (tabView.views[i] == tabPage) {
			tabView.views.splice(i, 1);
			break;
		}
	}
	for (let i = 0; i < tabView.tabPages.length; i++) {
		if (tabView.tabPages[i] == tabPage) {
			tabView.tabPages.splice(i, 1);
			break;
		}
	}
}

/*
* 选中页
* tabView:多页夹
* tabPage:页
*/
function selectTabPage(tabView : FCTabView, tabPage : FCTabPage) {
	for (let i = 0; i < tabView.tabPages.length; i++) {
		let tp = tabView.tabPages[i];
		if (tp == tabPage) {
			tp.visible = true;
		} else {
			tp.visible = false;
		}
	}
	updateTabLayout(tabView);
}

//动画中的页夹
let animationTabPages : Array<FCTabPage> = [];

/*
* 检查页的动画
*/
function checkTabPageAnimation() {
	if (animationTabPages.length > 0) {
		for (let i = 0; i < animationTabPages.length; i++) {
			let tp = animationTabPages[i];
			if (tp.parent) {
				let tabView = (tp.parent as any) as FCTabView;
				if (tabView.underPoint) {
					let location = tp.headerButton!.location;
					if (location.x > tabView.underPoint.x) {
						tabView.underPoint.x += tabView.animationSpeed;
					}
					else if (location.x < tabView.underPoint.x) {
						tabView.underPoint.x -= tabView.animationSpeed;
					}
					if (location.y > tabView.underPoint.y) {
						tabView.underPoint.y += tabView.animationSpeed;
					}
					else if (location.y < tabView.underPoint.y) {
						tabView.underPoint.y -= tabView.animationSpeed;
					}
					if (Math.abs(location.x - tabView.underPoint.x) <= tabView.animationSpeed && Math.abs(location.y - tabView.underPoint.y) <= tabView.animationSpeed) {
						tabView.underPoint = null as any;
						animationTabPages.splice(i, 1);
					}
				}
				if (tp.parent.paint != null) {
					invalidateView(tp.parent);
				}
			} else {
				animationTabPages.splice(i, 1);
			}
			break;
		}
	}
}

/*
* 重绘多页加
* tabView:多页夹
* paint:绘图对象
* clipRect:裁剪区域
*/
function drawTabViewBorder(tabView : FCTabView, paint : FCPaint, clipRect : FCRect) {
	if (tabView.underLineColor != null) {
		for (let i = 0; i < tabView.tabPages.length; i++) {
			let tp = tabView.tabPages[i];
			if (tp.visible) {
				let headerButton = tp.headerButton as FCView;
				let location = new FCPoint(headerButton.location.x, headerButton.location.y);
				let size = headerButton.size;
				if (tabView.useAnimation) {
					if (tabView.underPoint != null) {
						location.x = tabView.underPoint.x;
						location.y = tabView.underPoint.y;
					}
				}
				if (tabView.layout == "bottom") {
					paint.fillRect(tabView.underLineColor!, location.x, location.y, location.x + size.cx, location.y + tabView.underLineSize);
				} else if (tabView.layout == "left") {
					paint.fillRect(tabView.underLineColor!, location.x + size.cx - tabView.underLineSize, location.y, location.x + size.cx, location.y + size.cy);
				} else if (tabView.layout == "top") {
					paint.fillRect(tabView.underLineColor!, location.x, location.y + size.cy - tabView.underLineSize, location.x + size.cx, location.y + size.cy);
				}
				else if (tabView.layout == "right") {
					paint.fillRect(tabView.underLineColor!, location.x, location.y, location.x + tabView.underLineSize, location.y + size.cy);
				}
				break;
			}
		}
	}
}

/*
* 获取总的偏移量
* node:树节点
*/
function getTotalIndent(node : FCTreeNode) : number {
	if (node.parentNode != null) {
		return node.indent + getTotalIndent(node.parentNode!);
	} else {
		return node.indent;
	}
}

/*
* 绘制单元格
* tree:树
* row:行
* column:列
* node:节点
* paint:绘图对象
* left:左侧坐标
* top:上方坐标
* right:右侧坐标
* bottom:下方坐标
*/
function drawTreeNode(tree : FCTree, row : FCTreeRow, column : FCTreeColumn, node : FCTreeNode, paint : FCPaint, left : number, top : number, right : number, bottom : number) {
	if (node.backColor != null && node.backColor != "none") {
		paint.fillRect(node.backColor, left, top, right, bottom);
	}
	if (node.value != null) {
		let tSize = paint.textSize(node.value, node.font);
		let tLeft = left + 2 + getTotalIndent(node);

		let wLeft = tLeft;
		let cR = tree.checkBoxWidth / 3;
		if (tree.showCheckBox) {
			wLeft += tree.checkBoxWidth;
			if (node.checked) {
				paint.fillRect(node.textColor, tLeft + (tree.checkBoxWidth - cR) / 2, top + (tree.rowHeight - cR) / 2, tLeft + (tree.checkBoxWidth + cR) / 2, top + (tree.rowHeight + cR) / 2);
			} else {
				paint.drawRect(node.textColor, 1, null, tLeft + (tree.checkBoxWidth - cR) / 2, top + (tree.rowHeight - cR) / 2, tLeft + (tree.checkBoxWidth + cR) / 2, top + (tree.rowHeight + cR) / 2);
			}
		}
		if (node.childNodes.length > 0) {
			paint.beginPath();
			if (node.collapsed) {
				paint.addLine(wLeft + (tree.collapsedWidth + cR) / 2, top + tree.rowHeight / 2, wLeft + (tree.collapsedWidth - cR) / 2, top + (tree.rowHeight - cR) / 2);
				paint.addLine(wLeft + (tree.collapsedWidth - cR) / 2, top + (tree.rowHeight - cR) / 2, wLeft + (tree.collapsedWidth - cR) / 2, top + (tree.rowHeight + cR) / 2);
				paint.addLine(wLeft + (tree.collapsedWidth - cR) / 2, top + (tree.rowHeight + cR) / 2, wLeft + (tree.collapsedWidth + cR) / 2, top + tree.rowHeight / 2);
			} else {
				paint.addLine(wLeft + (tree.collapsedWidth - cR) / 2, top + (tree.rowHeight - cR) / 2, wLeft + (tree.collapsedWidth + cR) / 2, top + (tree.rowHeight - cR) / 2);
				paint.addLine(wLeft + (tree.collapsedWidth + cR) / 2, top + (tree.rowHeight - cR) / 2, wLeft + tree.collapsedWidth / 2, top + (tree.rowHeight + cR) / 2);
				paint.addLine(wLeft + tree.collapsedWidth / 2, top + (tree.rowHeight + cR) / 2, wLeft + (tree.collapsedWidth - cR) / 2, top + (tree.rowHeight - cR) / 2);
			}
			paint.fillPath(node.textColor);
			paint.closePath();
			wLeft += tree.collapsedWidth;
		}
		if (tSize.cx > column.width) {
			paint.drawTextAutoEllipsis(node.value, node.textColor, node.font, wLeft, top + tree.rowHeight / 2 - tSize.cy / 2, wLeft + column.width, top + tree.rowHeight / 2 - tSize.cy / 2);
		} else {
			paint.drawText(node.value, node.textColor, node.font, wLeft, top + tree.rowHeight / 2 - tSize.cy / 2);
		}
	}
}

/*
* 绘制树
* tree:树
* paint:绘图对象
* clipRect:裁剪区域
*/
function drawTree(tree : FCTree, paint : FCPaint, clipRect : FCRect) {
	let cLeft = -tree.scrollH;
	let cTop = -tree.scrollV + tree.headerHeight;
	//绘制行
	let colLeft = 0;
	for (let i = 0; i < tree.columns.length; i++) {
		let colRect = new FCRect(colLeft, 0, colLeft + tree.columns[i].width, tree.headerHeight);
		tree.columns[i].bounds = colRect;
		tree.columns[i].index = i;
		colLeft += tree.columns[i].width;
	}
	updateTreeRowIndex(tree);
	for (let i = 0; i < tree.rows.length; i++) {
		let row = tree.rows[i];
		if (row.visible) {
			let rTop = cTop, rBottom = cTop + tree.rowHeight;
			if (rBottom >= 0 && cTop <= tree.size.cy) {
				for (let j = 0; j < row.cells.length; j++) {
					let node = row.cells[j];
					let treeColumn = node.column;
					if (treeColumn == null) {
						treeColumn = tree.columns[j];
					}
					if (treeColumn.visible) {
						let nodeWidth = treeColumn.width;
						let nodeHeight = tree.rowHeight;
						let cRect = new FCRect(treeColumn.bounds.left - tree.scrollH, rTop, treeColumn.bounds.left + nodeWidth - tree.scrollH, rTop + nodeHeight);
						if (cRect.right >= 0 && cRect.left < tree.size.cx) {
							if (paint.onPaintTreeNode != null) {
								paint.onPaintTreeNode!(tree, row, treeColumn, node, paint, cRect.left, cRect.top, cRect.right, cRect.bottom);
							} else {
								drawTreeNode(tree, row, treeColumn, node, paint, cRect.left, cRect.top, cRect.right, cRect.bottom);
							}
						}
					}
				}
			}
			if (cTop > tree.size.cy) {
				break;
			}
			cTop += tree.rowHeight;
		}
	}
}

/*
* 绘制滚动条
* tree:树
* paint:绘图对象
* clipRect:裁剪区域
*/
function drawTreeScrollBar(tree : FCTree, paint : FCPaint, clipRect : FCRect) {
	tree.hScrollIsVisible = false;
	tree.vScrollIsVisible = false;
	if (paint.isMobile) {
		if (paint.touchDownView == tree) {
		} else if (g_dragScrollView_Tree == tree && g_scrollAddSpeed_Tree != 0) {
		} else {
			return;
		}
	}
	if (tree.showHScrollBar) {
		let contentWidth = getTreeContentWidth(tree);
		if (contentWidth > 0 && contentWidth > tree.size.cx) {
			let sLeft = tree.scrollH / contentWidth * tree.size.cx;
			let sRight = (tree.scrollH + tree.size.cx) / contentWidth * tree.size.cx;
			if (sRight - sLeft < tree.scrollSize) {
				sRight = sLeft + tree.scrollSize;
			}
			if (paint.touchMoveView == tree && (tree.hoverScrollHButton || tree.downScrollHButton)) {
				paint.fillRect(tree.scrollBarHoveredColor, sLeft, tree.size.cy - tree.scrollSize, sRight, tree.size.cy);
			} else {
				paint.fillRect(tree.scrollBarColor, sLeft, tree.size.cy - tree.scrollSize, sRight, tree.size.cy);
			}
			tree.hScrollIsVisible = true;
		}
	}
	if (tree.showVScrollBar) {
		let contentHeight = getTreeContentHeight(tree);
		if (contentHeight > 0 && contentHeight > tree.size.cy) {
			let sTop = tree.headerHeight + tree.scrollV / contentHeight * (tree.size.cy - tree.headerHeight - tree.scrollSize);
			let sBottom = sTop + ((tree.size.cy - tree.headerHeight)) / contentHeight * (tree.size.cy - tree.headerHeight - tree.scrollSize);
			if (sBottom - sTop < tree.scrollSize) {
				sBottom = sTop + tree.scrollSize;
			}
			if (paint.touchMoveView == tree && (tree.hoverScrollVButton || tree.downScrollVButton)) {
				paint.fillRect(tree.scrollBarHoveredColor, tree.size.cx - tree.scrollSize, sTop, tree.size.cx, sBottom);
			} else {
				paint.fillRect(tree.scrollBarColor, tree.size.cx - tree.scrollSize, sTop, tree.size.cx, sBottom);
			}
			tree.vScrollIsVisible = true;
		}
	}
}

/*
* 获取内容的宽度
* tree:树
*/
function getTreeContentWidth(tree : FCTree) : number {
	let cWidth = 0;
	for (let i = 0; i < tree.columns.length; i++) {
		if (tree.columns[i].visible) {
			cWidth += tree.columns[i].width;
		}
	}
	return cWidth;
}

/*
* 获取内容的高度
* tree:树
*/
function getTreeContentHeight(tree : FCTree) : number {
	let cHeight = 0;
	for (let i = 0; i < tree.rows.length; i++) {
		if (tree.rows[i].visible) {
			cHeight += tree.rowHeight;
		}
	}
	return cHeight;
}

/*
* 树的鼠标移动方法
* tree: 树
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
*/
function touchMoveTree(tree : FCTree, firstTouch : boolean, firstPoint : FCPoint, secondTouch : boolean, secondPoint : FCPoint) {
	tree.hoverScrollHButton = false;
	tree.hoverScrollVButton = false;
	let mp = firstPoint;
	if (firstTouch) {
		if (tree.showHScrollBar || tree.showVScrollBar) {
			if (tree.downScrollHButton) {
				let contentWidth = getTreeContentWidth(tree);
				let subX = (mp.x - tree.startPoint.x) / tree.size.cx * contentWidth;
				let newScrollH = tree.startScrollH + subX;
				if (newScrollH < 0) {
					newScrollH = 0;
				} else if (newScrollH > contentWidth - tree.size.cx) {
					newScrollH = contentWidth - tree.size.cx;
				}
				tree.scrollH = newScrollH;
				tree.paint!.cancelClick = true;
				return;

			} else if (tree.downScrollVButton) {
				let contentHeight = getTreeContentHeight(tree);
				let subY = (mp.y - tree.startPoint.y) / (tree.size.cy - tree.headerHeight - tree.scrollSize) * contentHeight;
				let newScrollV = tree.startScrollV + subY;
				if (newScrollV < 0) {
					newScrollV = 0;
				} else if (newScrollV > contentHeight - (tree.size.cy - tree.headerHeight - tree.scrollSize)) {
					newScrollV = contentHeight - (tree.size.cy - tree.headerHeight - tree.scrollSize);
				}
				tree.scrollV = newScrollV;
				tree.paint!.cancelClick = true;
				return;
			}
		}
		if (tree.allowDragScroll) {
			let contentWidth = getTreeContentWidth(tree);
			if (contentWidth > tree.size.cx) {
				let subX = tree.startPoint.x - mp.x;
				let newScrollH = tree.startScrollH + subX;
				if (newScrollH < 0) {
					newScrollH = 0;
				} else if (newScrollH > contentWidth - tree.size.cx) {
					newScrollH = contentWidth - tree.size.cx;
				}
				tree.scrollH = newScrollH;
				if (Math.abs(subX) > 5) {
					tree.paint!.cancelClick = true;
				}
			}
			let contentHeight = getTreeContentHeight(tree);
			if (contentHeight > tree.size.cy) {
				let subY = tree.startPoint.y - mp.y;
				let newScrollV = tree.startScrollV + subY;
				if (newScrollV < 0) {
					newScrollV = 0;
				} else if (newScrollV > contentHeight - (tree.size.cy - tree.headerHeight - tree.scrollSize)) {
					newScrollV = contentHeight - (tree.size.cy - tree.headerHeight - tree.scrollSize);
				}
				tree.scrollV = newScrollV;
				if (Math.abs(subY) > 5) {
					tree.paint!.cancelClick = true;
				}
			}
		}
	} else {
		if (tree.showHScrollBar) {
			let contentWidth = getTreeContentWidth(tree);
			if (contentWidth > 0 && contentWidth > tree.size.cx) {
				let sLeft = tree.scrollH / contentWidth * tree.size.cx;
				let sRight = (tree.scrollH + tree.size.cx) / contentWidth * tree.size.cx;
				if (sRight - sLeft < tree.scrollSize) {
					sRight = sLeft + tree.scrollSize;
				}
				if (mp.x >= sLeft && mp.x <= sRight && mp.y >= tree.size.cy - tree.scrollSize && mp.y <= tree.size.cy) {
					tree.hoverScrollHButton = true;
					return;
				} else {
					tree.hoverScrollHButton = false;
				}
			}
		}
		if (tree.showVScrollBar) {
			let contentHeight = getTreeContentHeight(tree);
			if (contentHeight > 0 && contentHeight > tree.size.cy) {
				let sTop = tree.headerHeight + tree.scrollV / contentHeight * (tree.size.cy - tree.headerHeight - tree.scrollSize);
				let sBottom = tree.headerHeight + (tree.scrollV + (tree.size.cy - tree.headerHeight - tree.scrollSize)) / contentHeight * (tree.size.cy - tree.headerHeight - tree.scrollSize);
				if (sBottom - sTop < tree.scrollSize) {
					sBottom = sTop + tree.scrollSize;
				}
				if (mp.x >= tree.size.cx - tree.scrollSize && mp.x <= tree.size.cx && mp.y >= sTop && mp.y <= sBottom) {
					tree.hoverScrollVButton = true;
					return;
				} else {
					tree.hoverScrollVButton = false;
				}
			}
		}
	}
}

/*
* 树的鼠标按下方法
* tree: 树
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
* clicks:点击次数
*/
function touchDownTree(tree : FCTree, firstTouch : boolean, firstPoint : FCPoint, secondTouch : boolean, secondPoint : FCPoint, clicks : number) {
	let mp = firstPoint;
	tree.touchDownTime = new Date().getTime()
	tree.startPoint = mp;
	tree.downScrollHButton = false;
	tree.downScrollVButton = false;
	g_dragScrollView_Tree = null;
	g_scrollAddSpeed_Tree = 0;
	g_scrollDirection_Tree = 0;
	if (tree.showHScrollBar) {
		let contentWidth = getTreeContentWidth(tree);
		if (contentWidth > 0 && contentWidth > tree.size.cx) {
			let sLeft = tree.scrollH / contentWidth * tree.size.cx;
			let sRight = (tree.scrollH + tree.size.cx) / contentWidth * tree.size.cx;
			if (sRight - sLeft < tree.scrollSize) {
				sRight = sLeft + tree.scrollSize;
			}
			if (mp.x >= sLeft && mp.x <= sRight && mp.y >= tree.size.cy - tree.scrollSize && mp.y <= tree.size.cy) {
				tree.downScrollHButton = true;
				tree.startScrollH = tree.scrollH;
				return;
			}
		}
	}
	if (tree.showVScrollBar) {
		let contentHeight = getTreeContentHeight(tree);
		if (contentHeight > 0 && contentHeight > tree.size.cy) {
			let sTop = tree.headerHeight + tree.scrollV / contentHeight * (tree.size.cy - tree.headerHeight - tree.scrollSize);
			let sBottom = tree.headerHeight + (tree.scrollV + (tree.size.cy - tree.headerHeight - tree.scrollSize)) / contentHeight * (tree.size.cy - tree.headerHeight - tree.scrollSize);
			if (sBottom - sTop < tree.scrollSize) {
				sBottom = sTop + tree.scrollSize;
			}
			if (mp.x >= tree.size.cx - tree.scrollSize && mp.x <= tree.size.cx && mp.y >= sTop && mp.y <= sBottom) {
				tree.downScrollVButton = true;
				tree.startScrollV = tree.scrollV;
				return;
			}
		}
	}
	if (tree.allowDragScroll) {
		tree.startScrollH = tree.scrollH;
		tree.startScrollV = tree.scrollV;
	}
	
	let cLeft = -tree.scrollH;
	let cTop = -tree.scrollV + tree.headerHeight;
	for (let i = 0; i < tree.rows.length; i++) {
		let row = tree.rows[i];
		if (row.visible) {
			if (firstPoint.y >= cTop && firstPoint.y <= cTop + tree.rowHeight) {
				let node = row.cells[0];
				let tLeft = cLeft + 2 + getTotalIndent(node);
				let wLeft = tLeft;
				if (tree.showCheckBox) {
					wLeft += tree.checkBoxWidth;
					if (firstPoint.x < wLeft) {
						checkOrUnCheckTreeNode(node, !node.checked);
						if (tree.paint != null) {
							invalidateView((tree as any) as FCView);
						}
						break;
					}
				}
				if (node.childNodes.length > 0) {
					wLeft += tree.collapsedWidth;
					if (firstPoint.x < wLeft) {
						node.collapsed = !node.collapsed;
						hideOrShowTreeNode(node, !node.collapsed);
						if (tree.paint != null) {
							invalidateView((tree as any) as FCView);
						}
						break;
					}
				}
				if (tree.paint != null && tree.paint!.onClickTreeNode != null) {
					tree.paint!.onClickTreeNode!(tree, node, firstTouch, firstPoint, secondTouch, secondPoint, clicks);
				}
			}
			cTop += tree.rowHeight;
		}
	}
}

let g_dragScrollView_Tree : FCTree | null = null;//正在滚动的表格
let g_scrollAddSpeed_Tree : number = 0;//滚动加速
let g_scrollDirection_Tree : number = 0; //滚动方向

/*
* 检查拖动滚动
*/
function checkDragScroll_Tree() {
	if (g_dragScrollView_Tree) {
		let sub = Math.floor(g_scrollAddSpeed_Tree / 10);
		if (sub == 0 && g_scrollAddSpeed_Tree > 1) {
			sub = 1;
		} else if (sub == 0 && g_scrollAddSpeed_Tree < -1) {
			sub = -1;
		}
		g_scrollAddSpeed_Tree -= sub;
		if (sub == 0) {
			let viewCache = g_dragScrollView_Tree;
			g_scrollAddSpeed_Tree = 0;
			g_dragScrollView_Tree = null as any;
			if (viewCache.paint != null) {
				invalidateView(viewCache);
			}

		} else {
			let viewCache = g_dragScrollView_Tree;
			let oldScrollV = Math.floor(viewCache.scrollV + g_scrollAddSpeed_Tree);
			let oldScrollH = Math.floor(viewCache.scrollH + g_scrollAddSpeed_Tree);
			if (g_scrollDirection_Tree == 0) {
				let contentHeight = getTreeContentHeight(viewCache);
				if (contentHeight < viewCache.size.cy) {
					viewCache.scrollV = 0;
				} else {
					if (oldScrollV < 0) {
						oldScrollV = 0;
					} else if (oldScrollV > contentHeight - viewCache.size.cy + viewCache.headerHeight + viewCache.scrollSize) {
						oldScrollV = contentHeight - viewCache.size.cy + viewCache.headerHeight + viewCache.scrollSize;
					}
					viewCache.scrollV = oldScrollV;
				}
			} else {
				let contentWidth = getTreeContentWidth(viewCache);
				if (contentWidth < viewCache.size.cx) {
					viewCache.scrollH = 0;
				} else {
					if (oldScrollH < 0) {
						oldScrollH = 0;
					} else if (oldScrollH > contentWidth - viewCache.size.cx) {
						oldScrollH = contentWidth - viewCache.size.cx;
					}
					viewCache.scrollH = oldScrollH;
				}
			}
			if (viewCache.paint != null) {
				invalidateView(viewCache);
			}
		}
	}
}

/*
* 表格的鼠标抬起方法
* tree: 树
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
* clicks:点击次数
*/
function touchUpTree(tree : FCTree, firstTouch : boolean, firstPoint : FCPoint, secondTouch : boolean, secondPoint : FCPoint, clicks : number) {
	tree.hoverScrollHButton = false;
	tree.hoverScrollVButton = false;
	if (firstTouch && !tree.downScrollHButton && !tree.downScrollVButton) {
		if (tree.allowDragScroll) {
			let touchUpTime = new Date().getTime();
			let diff = touchUpTime - tree.touchDownTime;
			//加速滚动
			if (diff < 250) {
				let sub1 = 100 * ((Math.abs(firstPoint.y - tree.startPoint.y)) / 20) / diff * 10;
				let sub2 = 100 * ((Math.abs(firstPoint.x - tree.startPoint.x)) / 20) / diff * 10;
				if ("A:" + sub1 != "A:NaN" && "A:" + sub2 != "A:NaN") {
					if (Math.abs(sub1) > Math.abs(sub2)) {
						if (firstPoint.y < tree.startPoint.y) {
							g_scrollAddSpeed_Tree += sub1;
						} else {
							g_scrollAddSpeed_Tree -= sub1;
						}
						g_scrollDirection_Tree = 0;
					} else {
						if (firstPoint.x < tree.startPoint.x) {
							g_scrollAddSpeed_Tree += sub2;
						} else {
							g_scrollAddSpeed_Tree -= sub2;
						}
						g_scrollDirection_Tree = 1;
					}
					g_dragScrollView_Tree = tree;
					if (Math.abs(g_scrollAddSpeed_Tree) > 0) {
						tree.paint!.cancelClick = true;
					}
				}
			}
		}
	}
	tree.downScrollHButton = false;
	tree.downScrollVButton = false;
}

/*
* 更新行的索引
* tree:树
*/
function updateTreeRowIndex(tree : FCTree) {
	for (let i = 0; i < tree.rows.length; i++) {
		tree.rows[i].index = i;
	}
}

/*
* 获取最后一行的索引
* node:树节点
*/
function getTreeLastNodeRowIndex(node : FCTreeNode) : number {
	let rowIndex = node.row!.index;
	for (let i = 0; i < node.childNodes.length; i++) {
		let rIndex = getTreeLastNodeRowIndex(node.childNodes[i]);
		if (rowIndex < rIndex) {
			rowIndex = rIndex;
		}
	}
	return rowIndex;
}

/*
* 添加节点
* tree:树
* node:要添加的节点
* parentNode:父节点
*/
function appendTreeNode(tree : FCTree, node : FCTreeNode, parentNode : FCTreeNode | null) {
	if (parentNode == null) {
		let newRow = new FCTreeRow();
		tree.rows.push(newRow);
		node.row = newRow;
		newRow.cells.push(node)
		tree.childNodes.push(node);
	} else {
		let newRow = new FCTreeRow();
		if (parentNode.childNodes.length == 0) {
			tree.rows.splice(parentNode.row!.index + 1, 0, newRow);
		} else {
			tree.rows.splice(getTreeLastNodeRowIndex(parentNode) + 1, 0, newRow);
		}
		node.parentNode = parentNode;
		node.indent = tree.indent;
		node.row = newRow;
		newRow.cells.push(node);
		parentNode.childNodes.push(node);
		if (parentNode.collapsed) {
			newRow.visible = false;
		}
	}
	updateTreeRowIndex(tree);
}

/*
* 移除节点
* tree:树
* node:要添加的节点
*/
function removeTreeNode(tree : FCTree, node : FCTreeNode) {
	//移除相互关系
	if (!node.parentNode) {
		let nodesSize = tree.childNodes.length;
		for (let i = 0; i < nodesSize; i++) {
			if (tree.childNodes[i] == node) {
				tree.childNodes.splice(i, 1);
				break;
			}
		}
	} else {
		let nodesSize = node.parentNode.childNodes.length;
		for (let i = 0; i < nodesSize; i++) {
			if (node.parentNode.childNodes[i] == node) {
				node.parentNode.childNodes.splice(i, 1);
				break;
			}
		}
	}
	//移除行
	tree.rows.splice(node.row!.index, 1);
	updateTreeRowIndex(tree);
}

/*
* 展开或折叠节点
* node:节点
* visible:是否可见
*/
function hideOrShowTreeNode(node : FCTreeNode, visible : boolean) {
	if (node.childNodes.length > 0) {
		for (let i = 0; i < node.childNodes.length; i++) {
			node.childNodes[i].row!.visible = visible;
			hideOrShowTreeNode(node.childNodes[i], visible);
		}
	}
}

/*
* 展开或折叠节点
* node:节点
* checked:是否选中
*/
function checkOrUnCheckTreeNode(node : FCTreeNode, checked : boolean) {
	node.checked = checked;
	if (node.childNodes.length > 0) {
		for (let i = 0; i < node.childNodes.length; i++) {
			checkOrUnCheckTreeNode(node.childNodes[i], checked);
		}
	}
}

/*
* 树的鼠标滚轮方法
* tree:树
* delta:滚轮值
*/
function touchWheelTree(tree : FCTree, delta : number) {
	let oldScrollV = tree.scrollV;
	if (delta < 0) {
		oldScrollV -= tree.rowHeight;
	} else if (delta > 0) {
		oldScrollV += tree.rowHeight;
	}
	let contentHeight = getTreeContentHeight(tree);
	if (contentHeight < tree.size.cy) {
		tree.scrollV = 0;
	} else {
		if (oldScrollV < 0) {
			oldScrollV = 0;
		} else if (oldScrollV > contentHeight - tree.size.cy + tree.headerHeight + tree.scrollSize) {
			oldScrollV = contentHeight - tree.size.cy + tree.headerHeight + tree.scrollSize;
		}
		tree.scrollV = oldScrollV;
	}
}

/*
 * 自动适应位置和大小
 * menu:菜单
 */
function adjustMenu(menu : FCMenu) {
	resetLayoutDiv(menu);
	if (menu.autoSize) {
		let contentHeight = getDivContentHeight(menu);
		let maximumHeight = menu.maximumSize.cy;
		menu.size.cy = Math.min(contentHeight, maximumHeight);
	}
	let mPoint = menu.location;
	let mSize = menu.size;
	let paint = menu.paint;
	let nSize = new FCSize((paint!.size.cx / paint!.ratio / paint!.scaleFactorX), (paint!.size.cy / paint!.ratio / paint!.scaleFactorY));
	if (mPoint.x < 0) {
		mPoint.x = 0;
	}
	if (mPoint.y < 0) {
		mPoint.y = 0;
	}
	if (mPoint.x + mSize.cx > nSize.cx) {
		mPoint.x = nSize.cx - mSize.cx;
	}
	if (mPoint.y + mSize.cy > nSize.cy) {
		mPoint.y = nSize.cy - mSize.cy;
	}
	menu.location = mPoint;
	menu.scrollV = 0;
}

/*
 * 添加菜单项
 * item:菜单项
 * menu:菜单
 */
function addMenuItem(item : FCMenuItem, menu : FCMenu) {
	addViewToParent(item, menu);
	item.parentMenu = menu;
	menu.items.push(item);
}

/*
 * 添加菜单项
 * item:菜单项
 * parentItem:父菜单项
 */
function addMenuItemToParent(item : FCMenuItem, parentItem : FCMenuItem) {
	item.parentItem = parentItem;
	if (!parentItem.dropDownMenu) {
		parentItem.dropDownMenu = new FCMenu();
		addView(parentItem.dropDownMenu, parentItem.paint!)
	}
	item.parentMenu = parentItem.dropDownMenu;
	addViewToParent(item, parentItem.dropDownMenu);
	parentItem.items.push(item);
	parentItem.dropDownMenu.items.push(item);
}

/*
 * 控制菜单的显示隐藏
 * paint:绘图对象
 */
function checkShowMenu(paint : FCPaint) {
	let paintAll = false;
	let clickItem = false;
	for (let i = 0; i < paint.views.length; i++) {
		let view = paint.views[i];
		if (view.viewType == "menu") {
			let menu = (view as any) as FCMenu;
			if (view.visible) {
				if (view == paint.touchDownView) {
					clickItem = true;
				}
				for (let j = 0; j < menu.items.length; j++) {
					let item = menu.items[j];
					if (item == paint.touchDownView) {
						clickItem = true;
						break;
					}
				}
			}
		}
	}
	if (!clickItem) {
		for (let i = 0; i < paint.views.length; i++) {
			let view = paint.views[i];
			if (view.viewType == "menu") {
				view.visible = false;
				paintAll = true;
			}
		}
	}
	if (paintAll) {
		invalidate(paint);
	}
}

/*
 * 关闭网格视图
 * items:菜单集合
 */
function closeMenus(items : Array<FCMenuItem>) : boolean {
	let itemSize = items.length;
	let close = false;
	for (let i = 0; i < itemSize; i++) {
		let item = items[i];
		let subItems = item.items;
		if (closeMenus(subItems)) {
			close = true;
		}
		let dropDownMenu = item.dropDownMenu as FCMenu;
		if (dropDownMenu != null && dropDownMenu.visible) {
			dropDownMenu.visible = false;
			close = true;
		}
	}
	return close;
}

/*
 * 鼠标移动到菜单项
 * item 菜单项
 */
function touchMoveMenuItem(item : FCMenuItem) {
	let parentItem = item.parentItem as FCMenuItem;
	let items : Array<FCMenuItem> = [];
	if (parentItem != null) {
		if (parentItem.dropDownMenu != null) {
			items = parentItem.dropDownMenu!.items;
		}
	} else {
		if (item.parentMenu != null) {
			items = item.parentMenu!.items;
		}
	}
	closeMenus(items);
	if (item.items.length > 0) {
		let dropDownMenu = item.dropDownMenu as FCMenu;
		//获取位置和大小
		if (dropDownMenu != null && !dropDownMenu.visible) {
			let layoutStyle = dropDownMenu.layoutStyle;
			let location = new FCPoint(clientX(item) + item.size.cx, clientY(item));
			if (layoutStyle == "lefttoright" || layoutStyle == "righttoleft") {
				location.x = clientX(item);
				location.y = clientY(item) + item.size.cy;
			}
			//设置弹出位置
			dropDownMenu.location = location;
			dropDownMenu.visible = true;
			adjustMenu(dropDownMenu);
			invalidate(item.paint!);
			return;
		}
	}
	invalidate(item.paint!);
};

/*
* 重绘按钮
* item:菜单项
* paint:绘图对象
* clipRect:裁剪区域
*/
function drawMenuItem(item : FCMenuItem, paint : FCPaint, clipRect : FCRect) {
	if (item == paint.touchDownView) {
		if (item.pushedColor != null && item.pushedColor != "nne") {
			paint.fillRect(item.pushedColor, 0, 0, item.size.cx, item.size.cy);
		} else {
			if (item.backColor != null && item.backColor != "none") {
				paint.fillRect(item.backColor, 0, 0, item.size.cx, item.size.cy);
			}
		}
	} else if (item == paint.touchMoveView) {
		if (item.hoveredColor != null && item.hoveredColor != "none") {
			paint.fillRect(item.hoveredColor!, 0, 0, item.size.cx, item.size.cy);
		} else {
			if (item.backColor != null && item.backColor != "none") {
				paint.fillRect(item.backColor, 0, 0, item.size.cx, item.size.cy);
			}
		}
	}
	else if (item.backColor != null && item.backColor != "none") {
		paint.fillRect(item.backColor, 0, 0, item.size.cx, item.size.cy);
	}
	if (item.textColor != null && item.textColor != "none" && item.text != null) {
		let tSize = paint.textSize(item.text, item.font);
		paint.drawText(item.text, item.textColor, item.font, (item.size.cx - tSize.cx) / 2, item.size.cy / 2 + 1 - tSize.cy / 2);
	}
	if (item.borderColor != null && item.borderColor != "none") {
		paint.drawRect(item.borderColor, item.borderWidth, [], 0, 0, item.size.cx, item.size.cy);
	}
	if (item.items.length > 0) {
		let tR = 5;
		paint.beginPath();
		paint.addLine(item.size.cx - 2, item.size.cy / 2, item.size.cx - 2 - tR * 2, item.size.cy / 2 - tR);
		paint.addLine(item.size.cx - 2 - tR * 2, item.size.cy / 2 - tR, item.size.cx - 2 - tR * 2, item.size.cy / 2 + tR);
		paint.addLine(item.size.cx - 2 - tR * 2, item.size.cy / 2 + tR, item.size.cx - 2, item.size.cy / 2);
		paint.fillPath(item.textColor);
		paint.closePath();
	}
}

/*
 * 点击菜单项
 * item:菜单项
 */
function clickMenuItem(item : FCMenuItem) {
	let paintAll = false;
	if (item.parentMenu != null) {
		if (item.parentMenu!.comboBox != null) {
			let index = -1;
			for (let i = 0; i < item.parentMenu!.items.length; i++) {
				if (item.parentMenu!.items[i] == item) {
					index = i;
					break;
				}
			}
			item.parentMenu!.comboBox!.selectedIndex = index;
			item.parentMenu!.comboBox!.text = item.parentMenu!.items[index].text;
			paintAll = true;
		}
	}
	if (item.items.length == 0) {
		for (let i = 0; i < item.paint!.views.length; i++) {
			let subView = item.paint!.views[i];
			if (subView.viewType == "menu") {
				if (subView.visible) {
					subView.visible = false;
					paintAll = true;
				}
			}
		}
	}
	if (paintAll) {
		invalidate(item.paint!);
	}
}

/*
* 重绘按钮
* comboBox:下拉列表
* paint:绘图对象
* clipRect:裁剪区域
*/
function drawComboBox(comboBox : FCComboBox, paint : FCPaint, clipRect : FCRect) {
	if (comboBox.backColor != null && comboBox.backColor != "none") {
		paint.fillRect(comboBox.backColor, 0, 0, comboBox.size.cx, comboBox.size.cy);
	}
	if (comboBox.textColor != null && comboBox.textColor != "none" && comboBox.text != null) {
		let tSize = paint.textSize(comboBox.text, comboBox.font);
		paint.drawText(comboBox.text, comboBox.textColor, comboBox.font, 5, comboBox.size.cy / 2 + 1 - tSize.cy / 2);
	}
	if (comboBox.borderColor != null && comboBox.borderColor != "none") {
		paint.drawRect(comboBox.borderColor, comboBox.borderWidth, [], 0, 0, comboBox.size.cx, comboBox.size.cy);
	}
	let tR = 5;
	paint.beginPath();
	paint.addLine(comboBox.size.cx - 5 - tR * 2, comboBox.size.cy / 2 - tR, comboBox.size.cx - 5, comboBox.size.cy / 2 - tR);
	paint.addLine(comboBox.size.cx - 5, comboBox.size.cy / 2 - tR, comboBox.size.cx - 5 - tR, comboBox.size.cy / 2 + tR);
	paint.addLine(comboBox.size.cx - 5 - tR, comboBox.size.cy / 2 + tR, comboBox.size.cx - 5 - tR * 2, comboBox.size.cy / 2 - tR);
	paint.fillPath(comboBox.textColor);
	paint.closePath();
}

/*
 * 点击下拉菜单
 * comboBox:下拉菜单
 */
function clickComboBox(comboBox : FCComboBox) {
	let showX = clientX(comboBox);
	let showY = clientY(comboBox) + comboBox.size.cy;
	comboBox.dropDownMenu!.location = new FCPoint(showX, showY);
	comboBox.dropDownMenu!.visible = true;
	adjustMenu(comboBox.dropDownMenu!);
	invalidate(comboBox.paint!);
}

/*
* 格式化字符串
* fmt:格式化字符
* date:日期
*/
function dateFormat(fmt : string, date : Date) : string {
	let year = date.getFullYear();
	let month = date.getMonth() + 1;
	let day = date.getDay();
	let hour = date.getHours();
	let minute = date.getMinutes();
	let second = date.getSeconds();
	let formatStr = fmt.replace("YYYY", year.toString());
	if (month < 10) {
		formatStr = formatStr.replace("mm", "0" + month.toString());
	} else {
		formatStr = formatStr.replace("mm", month.toString());
	}
	if (month < 10) {
		formatStr = formatStr.replace("dd", "0" + day.toString());
	} else {
		formatStr = formatStr.replace("dd", day.toString());
	}
	if (hour < 10) {
		formatStr = formatStr.replace("HH", "0" + hour.toString());
	} else {
		formatStr = formatStr.replace("HH", hour.toString());
	}
	if (minute < 10) {
		formatStr = formatStr.replace("MM", "0" + minute.toString());
	} else {
		formatStr = formatStr.replace("MM", minute.toString());
	}
	if (second < 10) {
		formatStr = formatStr.replace("SS", "0" + second.toString());
	} else {
		formatStr = formatStr.replace("SS", second.toString());
	}
	return formatStr;
}

/*
* 计算直线参数
* mp:坐标
* x1:横坐标1
* y1:纵坐标1
* x2:横坐标2
* y2:纵坐标2
* oX:坐标起始X
* oY:坐标起始Y
*/
function lineXY(chart : FCChart, x1 : number, y1 : number, x2 : number, y2 : number, oX : number, oY : number) {
	chart.kChart = 0;
	chart.bChart = 0;
	if ((x1 - oX) != (x2 - oX)) {
		chart.kChart = ((y2 - oY) - (y1 - oY)) / ((x2 - oX) - (x1 - oX));
		chart.bChart = (y1 - oY) - chart.kChart * (x1 - oX);
	}
}

/*
* 判断是否选中直线
* mp:坐标
* x1:横坐标1
* y1:纵坐标1
* x2:横坐标2
* y2:纵坐标2
*/
function selectLine(chart : FCChart, mp : FCPoint, x1 : number, y1 : number, x2 : number, y2 : number) : boolean {
	lineXY(chart, x1, y1, x2, y2, 0, 0);
	if (!(chart.kChart == 0 && chart.bChart == 0)) {
		if (mp.y / (mp.x * chart.kChart + chart.bChart) >= 0.9 && mp.y / (mp.x * chart.kChart + chart.bChart) <= 1.1) {
			return true;
		}
	} else {
		if (mp.x >= x1 - chart.plotPointSizeChart && mp.x <= x1 + chart.plotPointSizeChart) {
			return true;
		}
	}
	return false;
}

/*
* 判断是否选中射线
* mp:坐标
* x1:横坐标1
* y1:纵坐标1
* x2:横坐标2
* y2:纵坐标2
*/
function selectRay(chart : FCChart, mp : FCPoint, x1 : number, y1 : number, x2 : number, y2 : number) : boolean {
	lineXY(chart, x1, y1, x2, y2, 0, 0);
	if (!(chart.kChart == 0 && chart.bChart == 0)) {
		if (mp.y / (mp.x * chart.kChart + chart.bChart) >= 0.9 && mp.y / (mp.x * chart.kChart + chart.bChart) <= 1.1) {
			if (x1 >= x2) {
				if (mp.x > x1 + chart.plotPointSizeChart) {
					return false;
				}
			} else if (x1 < x2) {
				if (mp.x < x1 - chart.plotPointSizeChart) {
					return false;
				}
			}
			return true;
		}
	} else {
		if (mp.x >= x1 - chart.plotPointSizeChart && mp.x <= x1 + chart.plotPointSizeChart) {
			if (y1 >= y2) {
				if (mp.y <= y1 - chart.plotPointSizeChart) {
					return true;
				}
			} else {
				if (mp.y >= y1 - chart.plotPointSizeChart) {
					return true;
				}
			}
		}
	}
	return false;
}

/*
* 判断是否选中线段
* mp:坐标
* x1:横坐标1
* y1:纵坐标1
* x2:横坐标2
* y2:纵坐标2
*/
function selectSegment(chart : FCChart, mp : FCPoint, x1 : number, y1 : number, x2 : number, y2 : number) : boolean {
	lineXY(chart, x1, y1, x2, y2, 0, 0);
	let smallX = x1 <= x2 ? x1 : x2;
	let smallY = y1 <= y2 ? y1 : y2;
	let bigX = x1 > x2 ? x1 : x2;
	let bigY = y1 > y2 ? y1 : y2;
	if (mp.x >= smallX - 2 && mp.x <= bigX + 2 && mp.y >= smallY - 2 && mp.y <= bigY + 2) {
		if (chart.kChart != 0 || chart.bChart != 0) {
			if (mp.y / (mp.x * chart.kChart + chart.bChart) >= 0.9 && mp.y / (mp.x * chart.kChart + chart.bChart) <= 1.1) {
				return true;
			}
		} else {
			if (mp.x >= x1 - chart.plotPointSizeChart && mp.x <= x1 + chart.plotPointSizeChart) {
				return true;
			}
		}
	}
	return false;
}

/*
* 根据三点计算圆心
* x1:横坐标1
* y1:纵坐标1
* x2:横坐标2
* y2:纵坐标2
* x3:横坐标3
* y3:纵坐标3
*/
function ellipseOR(chart : FCChart, x1 : number, y1 : number, x2 : number, y2 : number, x3 : number, y3 : number) {
	chart.oXChart = ((y3 - y1) * (y2 * y2 - y1 * y1 + x2 * x2 - x1 * x1) + (y2 - y1) * (y1 * y1 - y3 * y3 + x1 * x1 - x3 * x3))
		/ (2 * (x2 - x1) * (y3 - y1) - 2 * (x3 - x1) * (y2 - y1));
	chart.oYChart = ((x3 - x1) * (x2 * x2 - x1 * x1 + y2 * y2 - y1 * y1) + (x2 - x1) * (x1 * x1 - x3 * x3 + y1 * y1 - y3 * y3))
		/ (2 * (y2 - y1) * (x3 - x1) - 2 * (y3 - y1) * (x2 - x1));
	chart.rChart = Math.sqrt((x1 - chart.oXChart) * (x1 - chart.oXChart) + (y1 - chart.oYChart) * (y1 - chart.oYChart));
}

/*
* 判断点是否在椭圆上
* x:横坐标
* y:纵坐标
* oX:坐标起始X
* oY:坐标起始Y
* a:椭圆参数a
* b:椭圆参数b
*/
function ellipseHasPoint(x : number, y : number, oX : number, oY : number, a : number, b : number) : boolean {
	let nx = x - oX;
	let ny = y - oY;
	if (a == 0 && b == 0 && nx == 0 && ny == 0) {
		return true;
	}
	if (a == 0) {
		if (nx == 0 && ny >= -b && ny <= b) {
			return false;
		}
	}
	if (b == 0) {
		if (ny == 0 && nx >= -a && nx <= a) {
			return true;
		}
	}
	if ((nx * nx) / (a * a) + (ny * ny) / (b * b) >= 0.8 && (nx * nx) / (a * a) + (ny * ny) / (b * b) <= 1.2) {
		return true;
	}
	return false;
}

/*
* 计算线性回归
* list:集合
*/
function linearRegressionEquation(chart : FCChart, list : Array<number>) : number {
	let result = 0;
	let sumX = 0;
	let sumY = 0;
	let sumUp = 0;
	let sumDown = 0;
	let xAvg = 0;
	let yAvg = 0;
	chart.kChart = 0;
	chart.bChart = 0;
	let length = list.length;
	let i = 0;
	if (length > 1) {
		for (i = 0; i < length; i++) {
			sumX += i + 1;
			sumY += list[i];
		}
		xAvg = sumX / length;
		yAvg = sumY / length;
		for (i = 0; i < length; i++) {
			sumUp += (i + 1 - xAvg) * (list[i] - yAvg);
			sumDown += (i + 1 - xAvg) * (i + 1 - xAvg);
		}
		chart.kChart = sumUp / sumDown;
		chart.bChart = yAvg - chart.kChart * xAvg;
	}
	return result;
}

/*
* 计算最大值
* list:集合
*/
function maxValue(list : Array<number>) : number {
	let length = list.length;
	let max = 0;
	for (let i = 0; i < length; i++) {
		if (i == 0) {
			max = list[i];
		}
		else {
			if (max < list[i]) {
				max = list[i];
			}
		}
	}
	return max;
}

/*
* 计算最小值
* list:集合
*/
function minValue(list : Array<number>) : number {
	let length = list.length;
	let min = 0;
	for (let i = 0; i < length; i++) {
		if (i == 0) {
			min = list[i];
		}
		else {
			if (min > list[i]) {
				min = list[i];
			}
		}
	}
	return min;
}

/*
* 计算平均值
* list:集合
*/
function avgValue(list : Array<number>) : number {
	let sum = 0;
	let length = list.length;
	if (length > 0) {
		for (let i = 0; i < length; i++) {
			sum += list[i];
		}
		return sum / length;
	}
	return 0;
}

/*
* 计算平行四边形参数
* x1:横坐标1
* y1:纵坐标1
* x2:横坐标2
* y2:纵坐标2
* x3:横坐标3
* y3:纵坐标3
*/
function parallelogram(chart : FCChart, x1 : number, y1 : number, x2 : number, y2 : number, x3 : number, y3 : number) {
	chart.x4Chart = x1 + x3 - x2;
	chart.y4Chart = y1 + y3 - y2;
}

/*
* 计算斐波那契数列
* index:索引
*/
function fibonacciValue(index : number) : number {
	if (index < 1) {
		return 0;
	}
	else {
		let vList : Array<number> = [];
		for (let i = 0; i < index; i++) {
			vList.push(0);
		}
		let result = 0;
		for (let i = 0; i <= index - 1; i++) {
			if (i == 0 || i == 1) {
				vList[i] = 1;
			}
			else {
				vList[i] = vList[i - 1] + vList[i - 2];
			}
		}
		result = vList[index - 1];
		return result;
	}
}

/*
* 获取图表的区域
* chart: 图表
* plot: 画线
*/
function getCandleRange(chart : FCChart, plot : FCPlot) {
	let bIndex = getChartIndexByDate(chart, plot.key1);
	let eIndex = getChartIndexByDate(chart, plot.key2);
	let tempBIndex = Math.min(bIndex, eIndex);
	let tempEIndex = Math.max(bIndex, eIndex);
	bIndex = tempBIndex;
	eIndex = tempEIndex;
	let highList : Array<number> = [];
	let lowList : Array<number> = [];
	for (let i = bIndex; i <= eIndex; i++) {
		highList.push(chart.data[i].high);
		lowList.push(chart.data[i].low);
	}
	chart.nHighChart = maxValue(highList);
	chart.nLowChart = minValue(lowList);
}

/*
* 获取百分比线的刻度
* y1: 纵坐标1
* y2: 纵坐标2
*/
function getPercentParams(y1 : number, y2 : number) : Array<number> {
	let list : Array<number> = [];
	let y0 = 0, y25 = 0, y50 = 0, y75 = 0, y100 = 0;
	y0 = y1;
	y25 = y1 <= y2 ? y1 + (y2 - y1) / 4 : y2 + (y1 - y2) * 3 / 4;
	y50 = y1 <= y2 ? y1 + (y2 - y1) / 2 : y2 + (y1 - y2) / 2;
	y75 = y1 <= y2 ? y1 + (y2 - y1) * 3 / 4 : y2 + (y1 - y2) / 4;
	y100 = y2;
	list.push(y0);
	list.push(y25);
	list.push(y50);
	list.push(y75);
	list.push(y100);
	return list;
}

/*
* 根据坐标计算矩形
* x1:横坐标1
* y1:纵坐标1
* x2:横坐标2
* y2:纵坐标2
*/
function rectangleXYWH(chart : FCChart, x1 : number, y1 : number, x2 : number, y2 : number) {
	chart.xChart = x1 < x2 ? x1 : x2;
	chart.yChart = y1 < y2 ? y1 : y2;
	chart.wChart = x1 - x2 > 0 ? x1 - x2 : x2 - x1;
	chart.hChart = y1 - y2 > 0 ? y1 - y2 : y2 - y1;
	if (chart.wChart <= 0) {
		chart.wChart = 4;
	}
	if (chart.hChart <= 0) {
		chart.hChart = 4;
	}
}

/*
 * 计算最大值
 * @param {Object} ticks 最高价数组
 * @param {Object} days
 */
function hhvValue(ticks : Array<number>, days : number) : Array<number> {
	let hhv : Array<number> = [];
	let max = ticks[0];
	for (let i = 0; i < ticks.length; i++) {
		if (i >= days) {
			max = ticks[i];
			for (let j = i; j > i - days; j--) {
				if (max < ticks[j]) {
					max = ticks[j];
				}
			}
			hhv.push(max);
		} else {
			if (max < ticks[i]) {
				max = ticks[i];
			}
			hhv.push(max);
		}
	}
	return hhv;
}

/*
 * 计算最小值
 * @param {Object} ticks 最低价数组
 * @param {Object} days
 */
function llvValue(ticks : Array<number>, days : number) : Array<number> {
	let llv : Array<number> = [];
	let min = ticks[0];
	for (let i = 0; i < ticks.length; i++) {
		if (i >= days) {
			min = ticks[i];
			for (let j = i; j > i - days; j--) {
				if (min > ticks[j]) {
					min = ticks[j];
				}
			}
			llv.push(min);
		} else {
			if (min > ticks[i]) {
				min = ticks[i];
			}
			llv.push(min);
		}
	}
	return llv;
}

/*
* REF函数
* ticks:数据
* days:日数
*/
function refValue(ticks : Array<number>, days : number) : Array<number> {
	let refArr : Array<number> = [];
	let length = ticks.length;
	for (let i = 0; i < length; i++) {
		let ref = 0;
		if (i >= days) {
			ref = ticks[i - days];
		} else {
			ref = ticks[0];
		}
		refArr.push(ref);
	}
	return refArr;
}

/*
* 获取TRIX的数据
* ticks:数据
*/
function getTRIXData(ticks : Array<number>, m : number, trixArr : Array<number>, matrixArr : Array<number>) {
	let length = ticks.length;
	let mtrArr : Array<number> = [];
	let emaArr1 : Array<number> = [];
	emaArr1.push(ticks[0]);
	for (let i = 1; i < length; i++) {
		emaArr1.push(getEMA(m, ticks[i], emaArr1[i - 1]));
	}

	let emaArr2 : Array<number> = [];
	emaArr2.push(emaArr1[0]);
	for (let i = 1; i < length; i++) {
		emaArr2.push(getEMA(m, emaArr1[i], emaArr2[i - 1]));
	}

	mtrArr.push(emaArr2[0]);
	for (let i = 1; i < length; i++) {
		mtrArr.push(getEMA(m, emaArr2[i], mtrArr[i - 1]));
	}

	let ref = refValue(mtrArr, 1);
	for (let i = 0; i < length; i++) {
		let trix = 100 * (mtrArr[i] - ref[i]) / ref[i];
		trixArr.push(trix);
	}

	let matrixArrCopy = maValue(trixArr, m);
	for (let i = 0; i < matrixArrCopy.length; i++) {
		matrixArr.push(matrixArrCopy[i]);
	}
}

/*
* 获取方差数据
*/
function standardDeviationSum(listValue : Array<number>, avgValue : number) : number {
	let targetValue = listValue[listValue.length - 1];
	let sumValue = (targetValue - avgValue) * (targetValue - avgValue);
	for (let i = 0; i < listValue.length - 1; i++) {
		let ileft = listValue[i];
		sumValue = sumValue + (ileft - avgValue) * (ileft - avgValue);
	}
	return sumValue;
}

/*
 * 计算boll指标,ma的周期为20日
 *
 * @method BOLL
 * @param {Array} ticks
 * 一维数组类型，每个元素为当前Tick的收盘价格
 * @return {Object} 返回一个包含upper mid lower属性的对象,每个属性对应的类型为{Array[Number]}
 */
function getBollData(ticks : Array<number>, maDays : number, ups : Array<number>, mas : Array<number>, lows : Array<number>) {
	let tickBegin = maDays - 1;
	let maSum = 0;
	let p = 0;
	for (let i = 0; i < ticks.length; i++) {
		let c = ticks[i];
		let ma = 0;
		let md = 0;
		let bstart = 0;
		let mdSum = 0;
		maSum = maSum + c;
		if (i >= tickBegin) {
			maSum = maSum - p;
			ma = maSum / maDays;
			bstart = i - tickBegin;
			p = ticks[bstart];
			mas.push(ma);
			bstart = i - tickBegin;
			p = ticks[bstart];
			let values : Array<number> = [];
			for (let j = bstart; j < bstart + maDays; j++) {
				values.push(ticks[j]);
			}
			mdSum = standardDeviationSum(values, ma);
			md = Math.sqrt(mdSum / maDays);
			ups.push(ma + 2 * md);
			lows.push(ma - 2 * md);
		}
		else {
			ma = maSum / (i + 1);
			mas.push(ma);
			let values : Array<number> = [];
			for (let j = 0; j < i + 1; j++) {
				values.push(ticks[j]);
			}
			mdSum = standardDeviationSum(values, ma);
			md = Math.sqrt(mdSum / (i + 1));
			ups.push(ma + 2 * md);
			lows.push(ma - 2 * md);
		}
	}
}

/*
 *
 * 计算kdj指标,rsv的周期为9日
 *
 * @method KDJ
 * @param {Array} ticks
 * 二维数组类型，其中内层数组包含三个元素值，第一个值表示当前Tick的最高价格，第二个表示当前Tick的最低价格，第三个表示当前Tick的收盘价格
 * @return {Object} 返回一个包含k d j属性的对象,每个属性对应的类型为{Array[Number]}
 */
function getKDJData(highArr : Array<number>, lowArr : Array<number>, closeArr : Array<number>, n : number, m1 : number, m2 : number, ks : Array<number>, ds : Array<number>, js : Array<number>) {
	let rsvs : Array<number> = [];
	let lastK = 0;
	let lastD = 0;
	let curK = 0;
	let curD = 0;
	for (let i = 0; i < closeArr.length; i++) {
		let highList : Array<number> = [];
		let lowList : Array<number> = [];
		let startIndex = i - n;
		if (startIndex < 0) {
			startIndex = 0;
		}

		for (let j = startIndex; j <= i; j++) {
			highList.push(highArr[j]);
			lowList.push(lowArr[j]);
		}

		let close = closeArr[i];
		let maxHigh = 0, minLow = 0;
		for (let m = 0; m < highList.length; m++) {
			let high = highList[m];
			let low = lowList[m];
			if (high > maxHigh) {
				maxHigh = high;
			}
			if (low < minLow) {
				minLow = low;
			}
		}
		if (maxHigh == minLow) {
			rsvs.push(0);
		}
		else {
			rsvs.push((close - minLow) / (maxHigh - minLow) * 100);
		}
		if (i == 0) {
			lastK = rsvs[i];
			lastD = rsvs[i];
		}
		curK = (m1 - 1) / m1 * lastK + 1.0 / m1 * rsvs[i];
		ks.push(curK);
		lastK = curK;

		curD = (m2 - 1) / m2 * lastD + 1.0 / m2 * curK;
		ds.push(curD);
		lastD = curD;

		js.push(3.0 * curK - 2.0 * curD);
	}
}

/*
 *
 * 计算rsi指标,分别返回以6日，12日，24日为参考基期的RSI值
 *
 * @method RSI
 * @param {Array} ticks
 * 一维数组类型，每个元素为当前Tick的收盘价格
 * @return {Object} 返回一个包含rsi6 rsi12 rsi24属性的对象,每个属性对应的类型为{Array[Number]}
 */
function getRSIData(ticks : Array<number>, n1 : number, n2 : number, n3 : number, rsi1 : Array<number>, rsi2 : Array<number>, rsi3 : Array<number>) {
	let lastClosePx = ticks[0];
	let lastSm1 = 0;
	let lastSa1 = 0;
	let lastSm2 = 0;
	let lastSa2 = 0;
	let lastSm3 = 0;
	let lastSa3 = 0;
	for (let i = 0; i < ticks.length; i++) {
		let c = ticks[i];
		let m = Math.max(c - lastClosePx, 0);
		let a = Math.abs(c - lastClosePx);
		if (i == 0) {
			lastSm1 = 0;
			lastSa1 = 0;
			rsi1.push(0);
		}
		else {
			lastSm1 = (m + (n1 - 1) * lastSm1) / n1;
			lastSa1 = (a + (n1 - 1) * lastSa1) / n1;
			if (lastSa1 != 0) {
				rsi1.push(lastSm1 / lastSa1 * 100);
			}
			else {
				rsi1.push(0);
			}
		}
		if (i == 0) {
			lastSm2 = 0;
			lastSa2 = 0;
			rsi2.push(0);
		}
		else {
			lastSm2 = (m + (n2 - 1) * lastSm2) / n2;
			lastSa2 = (a + (n2 - 1) * lastSa2) / n2;
			if (lastSa2 != 0) {
				rsi2.push(lastSm2 / lastSa2 * 100);
			}
			else {
				rsi2.push(0);
			}
		}
		if (i == 0) {
			lastSm3 = 0;
			lastSa3 = 0;
			rsi3.push(0);
		}
		else {
			lastSm3 = (m + (n3 - 1) * lastSm3) / n3;
			lastSa3 = (a + (n3 - 1) * lastSa3) / n3;
			if (lastSa3 != 0) {
				rsi3.push(lastSm3 / lastSa3 * 100);
			}
			else {
				rsi3.push(0.0);
			}
		}
		lastClosePx = c;
	}
}

/*
 * MA数据计算
 * @param {Object} ticks 收盘价数组
 * @param {Object} days 天数
 */
function maValue(ticks : Array<number>, days : number) : Array<number> {
	let maSum = 0;
	let mas : Array<number> = [];
	let last = 0;
	for (let i = 0; i < ticks.length; i++) {
		let ma = 0;
		if (i >= days) {
			last = ticks[i - days];
			maSum = maSum + ticks[i] - last;
			ma = maSum / days;
		} else {
			maSum += ticks[i];
			ma = maSum / (i + 1);
		}
		mas.push(ma);
	}
	return mas;
}

/*
 * 计算ROC数据
 * @param {Object} ticks 收盘价数组
 */
function getRocData(ticks : Array<number>, n : number, m : number, roc : Array<number>, maroc : Array<number>) {
	for (let i = 0; i < ticks.length; i++) {
		let currRoc = 0;
		if (i >= n) {
			currRoc = 100 * (ticks[i] - ticks[i - n]) / ticks[i - n];
			roc.push(currRoc);
		}
		else {
			currRoc = 100 * (ticks[i] - ticks[0]) / ticks[0];
			roc.push(currRoc);
		}
	}
	let marocMA = maValue(roc, m);
	for (let i = 0; i < marocMA.length; i++) {
		maroc.push(marocMA[i]);
	}
}

/*
 * 获取BIAS的数据
 * @param {Array} ticks 收盘价数组
 * @return
 */
function getBIASData(ticks : Array<number>, n1 : number, n2 : number, n3 : number, bias1Arr : Array<number>, bias2Arr : Array<number>, bias3Arr : Array<number>) {
	let ma1 = maValue(ticks, n1);
	let ma2 = maValue(ticks, n2);
	let ma3 = maValue(ticks, n3);
	for (let i = 0; i < ticks.length; i++) {
		let b1 = (ticks[i] - ma1[i]) / ma1[i] * 100;
		let b2 = (ticks[i] - ma2[i]) / ma2[i] * 100;
		let b3 = (ticks[i] - ma3[i]) / ma3[i] * 100;
		bias1Arr.push(b1);
		bias2Arr.push(b2);
		bias3Arr.push(b3);
	}
}

/*
 * 计算BBI(多空指标)
 * @param {Object} ticks
 */
function getBBIData(ticks : Array<number>, n1 : number, n2 : number, n3 : number, n4 : number, bbiArr : Array<number>) {
	let ma3 = maValue(ticks, n1);
	let ma6 = maValue(ticks, n2);
	let ma12 = maValue(ticks, n3);
	let ma24 = maValue(ticks, n4);
	for (let i = 0; i < ticks.length; i++) {
		let bbi = (ma3[i] + ma6[i] + ma12[i] + ma24[i]) / 4;
		bbiArr.push(bbi);
	}
}

/*
 * 计算WR(威廉指标)
 * @param {Array} ticks 含最高价,最低价, 收盘价的二维数组
 * @param {Object} days
 */
function getWRData(highArr : Array<number>, lowArr : Array<number>, closeArr : Array<number>, n1 : number, n2 : number, wr1Arr : Array<number>, wr2Arr : Array<number>) {
	let highArr1 = hhvValue(highArr, n1);
	let highArr2 = hhvValue(highArr, n2);
	let lowArr1 = llvValue(lowArr, n1);
	let lowArr2 = llvValue(lowArr, n2);
	for (let i = 0; i < closeArr.length; i++) {
		let high1 = highArr1[i];
		let low1 = lowArr1[i];
		let high2 = highArr2[i];
		let low2 = lowArr2[i];
		let close = closeArr[i];
		let wr1 = 100 * (high1 - close) / (high1 - low1);
		let wr2 = 100 * (high2 - close) / (high2 - low2);
		wr1Arr.push(wr1);
		wr2Arr.push(wr2);
	}
}

/*
 * 计算DMA（平均差）
 * @param {Object} ticks 收盘价数组
 */
function getDMAData(ticks : Array<number>, n1 : number, n2 : number, difArr : Array<number>, difmaArr : Array<number>) {
	let ma10 = maValue(ticks, n1);
	let ma50 = maValue(ticks, n2);
	for (let i = 0; i < ticks.length; i++) {
		let dif = ma10[i] - ma50[i];
		difArr.push(dif);
	}
	let difma = maValue(difArr, n1);
	for (let i = 0; i < difma.length; i++) {
		difmaArr.push(difma[i]);
	}
}

/*
 * CCI(顺势指标)计算  CCI（N日）=（TP－MA）÷MD÷0.015
 * @param {Object} ticks 带最高价，最低价，收盘价的二维数组
 */
function getCCIData(highArr : Array<number>, lowArr : Array<number>, closeArr : Array<number>, n : number, cciArr : Array<number>) {
	let tpArr : Array<number> = [];
	for (let i = 0; i < closeArr.length; i++) {
		tpArr.push((closeArr[i] + highArr[i] + lowArr[i]) / 3);
	}
	let maClose = maValue(closeArr, n);

	let mdArr : Array<number> = [];
	for (let i = 0; i < closeArr.length; i++) {
		mdArr.push(maClose[i] - closeArr[i]);
	}
	let maMD = maValue(mdArr, n);
	for (let i = 0; i < closeArr.length; i++) {
		let cci = 0;
		if (maMD[i] > 0) {
			cci = (tpArr[i] - maClose[i]) / (maMD[i] * 0.015);
		}
		cciArr.push(cci);
	}
}

/*
* 图表的鼠标按下方法
* chart: 图表
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
*/
function touchDownChart(chart : FCChart, firstTouch : boolean, firstPoint : FCPoint, secondTouch : boolean, secondPoint : FCPoint) {
	let mp = firstPoint;
	chart.touchDownPointChart = mp;
	chart.crossStopIndex = getChartIndex(chart, mp);
	chart.selectShape = "";
	chart.selectShapeEx = "";
	chart.sPlot = selectPlot(chart, mp);
	if (chart.sPlot == null) {
		selectShape(chart, mp);
	}
	if(chart.paint!.isDoubleClick){
		chart.showCrossLine = !chart.showCrossLine;
	}
}

/*
* 添加画线
* chart: 图表
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
*/
function addPlotDefault(chart : FCChart, firstTouch : boolean, firstPoint : FCPoint, secondTouch : boolean, secondPoint : FCPoint) {
	let mp = firstPoint;
	if (mp.y < getCandleDivHeight(chart)) {
		let touchIndex = getChartIndex(chart, mp);
		if (touchIndex >= chart.firstVisibleIndex && touchIndex <= chart.lastVisibleIndex) {
			if (chart.addingPlotChart == "FiboTimezone") {
				let fIndex = touchIndex;
				let fDate = getChartDateByIndex(chart, fIndex);
				let y = getChartValue(chart, mp);
				let newPlot = new FCPlot();
				if (chart.paint!.defaultUIStyle == "light") {
					newPlot.lineColor = "rgb(0,0,0)";
					newPlot.pointColor = "rgba(0,0,0,125)";
				} else {
					newPlot.lineColor = "rgb(255,255,255)";
					newPlot.pointColor = "rgba(255,255,255,125)";
				}
				newPlot.key1 = fDate;
				newPlot.value1 = y;
				newPlot.plotType = chart.addingPlotChart;
				chart.plots.push(newPlot);
				chart.sPlot = selectPlot(chart, mp);
			}
			else if (chart.addingPlotChart == "Triangle" || chart.addingPlotChart == "CircumCycle" || chart.addingPlotChart == "ParalleGram" || chart.addingPlotChart == "AngleLine" || chart.addingPlotChart == "Parallel" || chart.addingPlotChart == "SymmetricTriangle") {
				let eIndex = touchIndex;
				let bIndex = eIndex - 5;
				if (bIndex >= 0) {
					let fDate = getChartDateByIndex(chart, bIndex);
					let sDate = getChartDateByIndex(chart, eIndex);
					let y = getChartValue(chart, mp);
					let newPlot = new FCPlot();
					if (chart.paint!.defaultUIStyle == "light") {
						newPlot.lineColor = "rgb(0,0,0)";
						newPlot.pointColor = "rgba(0,0,0,125)";
					} else {
						newPlot.lineColor = "rgb(255,255,255)";
						newPlot.pointColor = "rgba(255,255,255,125)";
					}
					newPlot.key1 = fDate;
					newPlot.value1 = y;
					newPlot.key2 = sDate;
					newPlot.value2 = y;
					newPlot.key3 = sDate;
					newPlot.value3 = chart.candleMin + (chart.candleMax - chart.candleMin) / 2;
					newPlot.plotType = chart.addingPlotChart;
					chart.plots.push(newPlot);
					chart.sPlot = selectPlot(chart, mp);
				}
			} else {
				let eIndex = touchIndex;
				let bIndex = eIndex - 5;
				if (bIndex >= 0) {
					let fDate = getChartDateByIndex(chart, bIndex);
					let sDate = getChartDateByIndex(chart, eIndex);
					let y = getChartValue(chart, mp);
					let newPlot = new FCPlot();
					if (chart.paint!.defaultUIStyle == "light") {
						newPlot.lineColor = "rgb(0,0,0)";
						newPlot.pointColor = "rgba(0,0,0,125)";
					} else {
						newPlot.lineColor = "rgb(255,255,255)";
						newPlot.pointColor = "rgba(255,255,255,125)";
					}
					newPlot.key1 = fDate;
					newPlot.value1 = y;
					newPlot.key2 = sDate;
					newPlot.value2 = y;
					newPlot.plotType = chart.addingPlotChart;
					chart.plots.push(newPlot);
					chart.sPlot = selectPlot(chart, mp);
				}
			}
		}
	}
}

/*
* 图表的鼠标移动方法
* chart: 图表
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
*/
function touchMoveChart(chart : FCChart, firstTouch : boolean, firstPoint : FCPoint, secondTouch : boolean, secondPoint : FCPoint) {
	if (chart.data == null || chart.data.length == 0) {
		return;
	}
	let mp = firstPoint;
	chart.crossStopIndex = getChartIndex(chart, mp);
	chart.touchPosition = mp;
	if (firstTouch && chart.sPlot != null) {
		let newIndex = getChartIndex(chart, mp);
		if (newIndex >= 0 && newIndex < chart.data.length) {
			let newDate = getChartDateByIndex(chart, newIndex);
			let newValue = getCandleDivValue(chart, mp);
			if (chart.selectPlotPoint == 0) {
				chart.sPlot!.key1 = newDate;
				chart.sPlot!.value1 = newValue;
			} else if (chart.selectPlotPoint == 1) {
				chart.sPlot!.key2 = newDate;
				chart.sPlot!.value2 = newValue;
			} else if (chart.selectPlotPoint == 2) {
				chart.sPlot!.key3 = newDate;
				chart.sPlot!.value3 = newValue;
			}
			else if (chart.startMovePlot) {
				let bValue = getCandleDivValue(chart, chart.touchDownPointChart);
				let bIndex = getChartIndex(chart, chart.touchDownPointChart);
				if (chart.sPlot!.key1 != 0) {
					chart.sPlot!.value1 = chart.sPlot!.startValue1 + (newValue - bValue);
					let startIndex1 = getChartIndexByDate(chart, chart.sPlot!.startKey1);
					let newIndex1 = startIndex1 + (newIndex - bIndex);
					if (newIndex1 < 0) {
						newIndex1 = 0;
					}
					else if (newIndex1 > chart.data.length - 1) {
						newIndex1 = chart.data.length - 1;
					}
					chart.sPlot!.key1 = getChartDateByIndex(chart, newIndex1);
				}
				if (chart.sPlot!.key2 != 0) {
					chart.sPlot!.value2 = chart.sPlot!.startValue2 + (newValue - bValue);
					let startIndex2 = getChartIndexByDate(chart, chart.sPlot!.startKey2);
					let newIndex2 = startIndex2 + (newIndex - bIndex);
					if (newIndex2 < 0) {
						newIndex2 = 0;
					}
					else if (newIndex2 > chart.data.length - 1) {
						newIndex2 = chart.data.length - 1;
					}
					chart.sPlot!.key2 = getChartDateByIndex(chart, newIndex2);
				}
				if (chart.sPlot!.key3 != 0) {
					chart.sPlot!.value3 = chart.sPlot!.startValue3 + (newValue - bValue);
					let startIndex3 = getChartIndexByDate(chart, chart.sPlot!.startKey3);
					let newIndex3 = startIndex3 + (newIndex - bIndex);
					if (newIndex3 < 0) {
						newIndex3 = 0;
					}
					else if (newIndex3 > chart.data.length - 1) {
						newIndex3 = chart.data.length - 1;
					}
					chart.sPlot!.key3 = getChartDateByIndex(chart, newIndex3);
				}
			}
		}
		return;
	}
	if (firstTouch && secondTouch) {
		if (firstPoint.x > secondPoint.x) {
			chart.firstTouchPointCacheChart = secondPoint;
			chart.secondTouchPointCacheChart = firstPoint;
		} else {
			chart.firstTouchPointCacheChart = firstPoint;
			chart.secondTouchPointCacheChart = secondPoint;
		}
		if (chart.firstTouchIndexCacheChart == -1 || chart.secondTouchIndexCacheChart == -1) {
			chart.firstTouchIndexCacheChart = getChartIndex(chart, chart.firstTouchPointCacheChart);
			chart.secondTouchIndexCacheChart = getChartIndex(chart, chart.secondTouchPointCacheChart);
			chart.firstIndexCacheChart = chart.firstVisibleIndex;
			chart.lastIndexCacheChart = chart.lastVisibleIndex;
		}
	} else if (firstTouch) {
		chart.secondTouchIndexCacheChart = -1;
		if (chart.firstTouchIndexCacheChart == -1) {
			chart.firstTouchPointCacheChart = firstPoint;
			chart.firstTouchIndexCacheChart = getChartIndex(chart, chart.firstTouchPointCacheChart);
			chart.firstIndexCacheChart = chart.firstVisibleIndex;
			chart.lastIndexCacheChart = chart.lastVisibleIndex;
			chart.firstPaddingTop = chart.candlePaddingTop;
			chart.firtstPaddingBottom = chart.candlePaddingBottom;
		}
	}

	if (firstTouch && secondTouch) {
		if (chart.firstTouchIndexCacheChart != -1 && chart.secondTouchIndexCacheChart != -1) {
			let fPoint = firstPoint;
			let sPoint = secondPoint;
			if (firstPoint.x > secondPoint.x) {
				fPoint = secondPoint;
				sPoint = firstPoint;;
			}
			let subX = Math.abs(sPoint.x - fPoint.x);
			let subIndex = Math.abs(chart.secondTouchIndexCacheChart - chart.firstTouchIndexCacheChart);
			if (subX > 0 && subIndex > 0) {
				let newScalePixel = subX / subIndex;
				if (newScalePixel >= 3) {
					let intScalePixel = Math.floor(newScalePixel);
					newScalePixel = intScalePixel;
				}
				if (newScalePixel != chart.hScalePixel) {
					let newFirstIndex = chart.firstTouchIndexCacheChart;
					let thisX = fPoint.x;
					thisX -= newScalePixel;
					while (thisX > chart.leftVScaleWidth + newScalePixel) {
						newFirstIndex--;
						if (newFirstIndex < 0) {
							newFirstIndex = 0;
							break;
						}
						thisX -= newScalePixel;
					}

					thisX = sPoint.x;
					let newSecondIndex = chart.secondTouchIndexCacheChart;
					thisX += newScalePixel;
					while (thisX < chart.size.cx - chart.rightVScaleWidth - newScalePixel) {
						newSecondIndex++;
						if (newSecondIndex > chart.data.length - 1) {
							newSecondIndex = chart.data.length - 1;
							break;
						}
						thisX += newScalePixel;
					}
					setChartVisibleIndex(chart, newFirstIndex, newSecondIndex);
					let maxVisibleRecord = getChartMaxVisibleCount(chart, chart.hScalePixel, getChartWorkAreaWidth(chart));
					while (maxVisibleRecord < chart.lastVisibleIndex - chart.firstVisibleIndex + 1
						&& chart.lastVisibleIndex > chart.firstVisibleIndex) {
						chart.lastVisibleIndex--;
					}
					checkChartLastVisibleIndex(chart);
					resetChartVisibleRecord(chart);
					if (chart.paint!.onCalculateChartMaxMin != null) {
						chart.paint!.onCalculateChartMaxMin!(chart);
					} else {
						calculateChartMaxMin(chart);
					}
				}
			}
		}
	} else if (firstTouch) {
		let subIndex = Math.floor((chart.firstTouchPointCacheChart.x - firstPoint.x) / chart.hScalePixel);
		if (chart.lastVisibleIndex + subIndex > chart.data.length - 1) {
			subIndex = chart.data.length - 1 - chart.lastIndexCacheChart;
		} else if (chart.firstVisibleIndex + subIndex < 0) {
			subIndex = -chart.firstIndexCacheChart;
		}
		if (chart.allowDragChartDiv) {
			chart.candlePaddingTop = chart.firstPaddingTop - (chart.firstTouchPointCacheChart.y - firstPoint.y);
			chart.candlePaddingBottom = chart.firtstPaddingBottom + (chart.firstTouchPointCacheChart.y - firstPoint.y);
		}
		chart.firstVisibleIndex = chart.firstIndexCacheChart + subIndex;
		chart.lastVisibleIndex = chart.lastIndexCacheChart + subIndex;
		checkChartLastVisibleIndex(chart);
		resetChartVisibleRecord(chart);
		if (chart.paint!.onCalculateChartMaxMin != null) {
			chart.paint!.onCalculateChartMaxMin!(chart);
		} else {
			calculateChartMaxMin(chart);
		}
	}
}

/*
* 绘制画线工具
* chart:图表
* paint:绘图对象
* clipRect:裁剪区域
*/
function drawChartPlot(chart : FCChart, paint : FCPaint, clipRect : FCRect) {
	paint.save();
	let divHeight = getCandleDivHeight(chart);
	paint.setClip(chart.leftVScaleWidth, 20, chart.size.cx - chart.rightVScaleWidth, divHeight);
	for (let i = 0; i < chart.plots.length; i++) {
		let plot = chart.plots[i];
		let index1 = 0, index2 = 0, index3 = 0;
		let mpx1 = 0, mpy1 = 0, mpx2 = 0, mpy2 = 0, mpx3 = 0, mpy3 = 0;
		if (plot.plotType == "LRLine" || plot.plotType == "LRChannel" || plot.plotType == "LRBand") {
			let list : Array<number> = [];
			index1 = getChartIndexByDate(chart, plot.key1);
			index2 = getChartIndexByDate(chart, plot.key2);
			let minIndex = Math.min(index1, index2);
			let maxIndex = Math.max(index1, index2);
			for (let j = minIndex; j <= maxIndex; j++) {
				list.push(chart.data[j].close);
			}
			linearRegressionEquation(chart, list);
			plot.value1 = chart.bChart;
			plot.value2 = chart.kChart * (maxIndex - minIndex + 1) + chart.bChart;
		}
		else if (plot.plotType == "BoxLine" || plot.plotType == "TironeLevels" || plot.plotType == "QuadrantLines") {
			getCandleRange(chart, plot);
			let nHigh = chart.nHighChart, nLow = chart.nLowChart;
			index1 = getChartIndexByDate(chart, plot.key1);
			index2 = getChartIndexByDate(chart, plot.key2);
			plot.key1 = getChartDateByIndex(chart, Math.min(index1, index2));
			plot.key2 = getChartDateByIndex(chart, Math.max(index1, index2));
			plot.value1 = nHigh;
			plot.value2 = nLow;
		}
		if (plot.key1 != 0) {
			index1 = getChartIndexByDate(chart, plot.key1);
			mpx1 = getChartX(chart, index1);
			mpy1 = getChartY(chart, 0, plot.value1);
			if (chart.sPlot == plot) {
				paint.fillEllipse(plot.pointColor, mpx1 - chart.plotPointSizeChart, mpy1 - chart.plotPointSizeChart, mpx1 + chart.plotPointSizeChart, mpy1 + chart.plotPointSizeChart);
			}
		}
		if (plot.key2 != 0) {
			index2 = getChartIndexByDate(chart, plot.key2);
			mpx2 = getChartX(chart, index2);
			mpy2 = getChartY(chart, 0, plot.value2);
			if (chart.sPlot == plot) {
				paint.fillEllipse(plot.pointColor, mpx2 - chart.plotPointSizeChart, mpy2 - chart.plotPointSizeChart, mpx2 + chart.plotPointSizeChart, mpy2 + chart.plotPointSizeChart);
			}
		}
		if (plot.key3 != 0) {
			index3 = getChartIndexByDate(chart, plot.key3);
			mpx3 = getChartX(chart, index3);
			mpy3 = getChartY(chart, 0, plot.value3);
			if (chart.sPlot == plot) {
				paint.fillEllipse(plot.pointColor, mpx3 - chart.plotPointSizeChart, mpy3 - chart.plotPointSizeChart, mpx3 + chart.plotPointSizeChart, mpy3 + chart.plotPointSizeChart);
			}
		}
		if (plot.plotType == "Line") {
			lineXY(chart, mpx1, mpy1, mpx2, mpy2, 0, 0);
			if (mpx2 == mpx1) {
				paint.drawLine(plot.lineColor, plot.lineWidth, null, mpx1, 0, mpx1, divHeight);
			} else {
				let newX1 = chart.leftVScaleWidth;
				let newY1 = newX1 * chart.kChart + chart.bChart;
				let newX2 = chart.size.cx - chart.rightVScaleWidth;
				let newY2 = newX2 * chart.kChart + chart.bChart;
				paint.drawLine(plot.lineColor, plot.lineWidth, null, newX1, newY1, newX2, newY2);
			}
		}
		else if (plot.plotType == "ArrowSegment") {
			let ARROW_Size = 24;
			let slopy = 0, cosy = 0, siny = 0;
			slopy = Math.atan2(mpy1 - mpy2, mpx1 - mpx2);
			cosy = Math.cos(slopy);
			siny = Math.sin(slopy);
			let ptPoint = new FCPoint(0, 0);
			ptPoint.x = mpx2;
			ptPoint.y = mpy2;
			let pts : Array<FCPoint> = [];
			pts.push(new FCPoint(0, 0));
			pts.push(new FCPoint(0, 0));
			pts.push(new FCPoint(0, 0));
			pts[0] = ptPoint;
			pts[1].x = ptPoint.x + (ARROW_Size * cosy - (ARROW_Size / 2.0 * siny) + 0.5);
			pts[1].y = ptPoint.y + (ARROW_Size * siny + (ARROW_Size / 2.0 * cosy) + 0.5);
			pts[2].x = ptPoint.x + (ARROW_Size * cosy + ARROW_Size / 2.0 * siny + 0.5);
			pts[2].y = ptPoint.y - (ARROW_Size / 2.0 * cosy - ARROW_Size * siny + 0.5);
			ARROW_Size = 20;
			let ptPoint2 = new FCPoint(0, 0);
			ptPoint2.x = mpx2;
			ptPoint2.y = mpy2;
			let pts2 : Array<FCPoint> = [];
			pts2.push(new FCPoint(0, 0));
			pts2.push(new FCPoint(0, 0));
			pts2.push(new FCPoint(0, 0));
			pts2[0] = ptPoint2;
			pts2[1].x = ptPoint2.x + (ARROW_Size * cosy - (ARROW_Size / 2.0 * siny) + 0.5);
			pts2[1].y = ptPoint2.y + (ARROW_Size * siny + (ARROW_Size / 2.0 * cosy) + 0.5);
			pts2[2].x = ptPoint2.x + (ARROW_Size * cosy + ARROW_Size / 2.0 * siny + 0.5);
			pts2[2].y = ptPoint2.y - (ARROW_Size / 2.0 * cosy - ARROW_Size * siny + 0.5);
			lineXY(chart, pts2[1].x, pts2[1].y, pts2[2].x, pts2[2].y, 0, 0);
			let newX1 = 0, newY1 = 0, newX2 = 0, newY2 = 0;
			if (pts2[1].x > pts2[2].x) {
				newX1 = pts2[2].x + (pts2[1].x - pts2[2].x) / 3;
				newX2 = pts2[2].x + (pts2[1].x - pts2[2].x) * 2 / 3;
			} else {
				newX1 = pts2[1].x + (pts2[2].x - pts2[1].x) / 3;
				newX2 = pts2[1].x + (pts2[2].x - pts2[1].x) * 2 / 3;
			}
			if (chart.kChart == 0 && chart.bChart == 0) {
				if (pts2[1].y > pts2[2].y) {
					newY1 = pts2[2].y + (pts2[1].y - pts2[2].y) / 3;
					newY2 = pts2[2].y + (pts2[1].y - pts2[2].y) * 2 / 3;
				} else {
					newY1 = pts2[1].y + (pts2[2].y - pts2[1].y) / 3;
					newY2 = pts2[1].y + (pts2[2].y - pts2[1].y) * 2 / 3;
				}
			} else {
				newY1 = (chart.kChart * newX1) + chart.bChart;
				newY2 = (chart.kChart * newX2) + chart.bChart;
			}
			pts2[1].x = newX1;
			pts2[1].y = newY1;
			pts2[2].x = newX2;
			pts2[2].y = newY2;
			let drawPoints : Array<FCPoint> = [];
			drawPoints.push(new FCPoint(0, 0));
			drawPoints.push(new FCPoint(0, 0));
			drawPoints.push(new FCPoint(0, 0));
			drawPoints.push(new FCPoint(0, 0));
			drawPoints.push(new FCPoint(0, 0));
			drawPoints.push(new FCPoint(0, 0));
			drawPoints[0].x = ptPoint.x;
			drawPoints[0].y = ptPoint.y;
			drawPoints[1].x = pts[1].x;
			drawPoints[1].y = pts[1].y;
			if (mpy1 >= mpy2) {
				drawPoints[2].x = pts2[1].x;
				drawPoints[2].y = pts2[1].y;
			} else {
				drawPoints[2].x = pts2[2].x;
				drawPoints[2].y = pts2[2].y;
			}
			drawPoints[3].x = mpx1;
			drawPoints[3].y = mpy1;
			if (mpy1 >= mpy2) {
				drawPoints[4].x = pts2[2].x;
				drawPoints[4].y = pts2[2].y;
			} else {
				drawPoints[4].x = pts2[1].x;
				drawPoints[4].y = pts2[1].y;
			}
			drawPoints[5].x = pts[2].x;
			drawPoints[5].y = pts[2].y;

			paint.beginPath();
			for (let j = 0; j < 6; j++) {
				if (j > 0) {
					paint.addLine(drawPoints[j - 1].x, drawPoints[j - 1].y, drawPoints[j].x, drawPoints[j].y);
				}
			}
			paint.fillPath(plot.lineColor);
			paint.closePath();
		}
		else if (plot.plotType == "AngleLine") {
			lineXY(chart, mpx1, mpy1, mpx2, mpy2, 0, 0);
			if (mpx2 == mpx1) {
				paint.drawLine(plot.lineColor, plot.lineWidth, null, mpx1, 0, mpx1, divHeight);
			} else {
				let newX1 = chart.leftVScaleWidth;
				let newY1 = newX1 * chart.kChart + chart.bChart;
				let newX2 = chart.size.cx - chart.rightVScaleWidth;
				let newY2 = newX2 * chart.kChart + chart.bChart;
				paint.drawLine(plot.lineColor, plot.lineWidth, null, newX1, newY1, newX2, newY2);
			}
			lineXY(chart, mpx1, mpy1, mpx3, mpy3, 0, 0);
			if (mpx3 == mpx1) {
				paint.drawLine(plot.lineColor, plot.lineWidth, null, mpx1, 0, mpx1, divHeight);
			} else {
				let newX1 = chart.leftVScaleWidth;
				let newY1 = newX1 * chart.kChart + chart.bChart;
				let newX2 = chart.size.cx - chart.rightVScaleWidth;
				let newY2 = newX2 * chart.kChart + chart.bChart;
				paint.drawLine(plot.lineColor, plot.lineWidth, null, newX1, newY1, newX2, newY2);
			}
		}
		else if (plot.plotType == "Parallel") {
			lineXY(chart, mpx1, mpy1, mpx2, mpy2, 0, 0);
			if (mpx2 == mpx1) {
				paint.drawLine(plot.lineColor, plot.lineWidth, null, mpx1, 0, mpx1, divHeight);
			} else {
				let newX1 = chart.leftVScaleWidth;
				let newY1 = newX1 * chart.kChart + chart.bChart;
				let newX2 = chart.size.cx - chart.rightVScaleWidth;
				let newY2 = newX2 * chart.kChart + chart.bChart;
				paint.drawLine(plot.lineColor, plot.lineWidth, null, newX1, newY1, newX2, newY2);
			}
			let newB = mpy3 - chart.kChart * mpx3;
			if (mpx2 == mpx1) {
				paint.drawLine(plot.lineColor, plot.lineWidth, null, mpx3, 0, mpx3, divHeight);
			} else {
				let newX1 = chart.leftVScaleWidth;
				let newY1 = newX1 * chart.kChart + newB;
				let newX2 = chart.size.cx - chart.rightVScaleWidth;
				let newY2 = newX2 * chart.kChart + newB;
				paint.drawLine(plot.lineColor, plot.lineWidth, null, newX1, newY1, newX2, newY2);
			}
		}
		else if (plot.plotType == "Percent") {
			let list = getPercentParams(mpy1, mpy2);
			let texts : Array<string> = [];
			texts.push("0%");
			texts.push("25%");
			texts.push("50%");
			texts.push("75%");
			texts.push("100%");
			for (let j = 0; j < list.length; j++) {
				paint.drawLine(plot.lineColor, plot.lineWidth, null, chart.leftVScaleWidth, list[j], chart.size.cx - chart.rightVScaleWidth, list[j]);
				let tSize = paint.textSize(texts[j], chart.font);
				paint.drawText(texts[j], chart.textColor, chart.font, chart.leftVScaleWidth + 5, list[j] - tSize.cy - 2);
			}
		}
		else if (plot.plotType == "FiboTimezone") {
			let fValue = 1;
			let aIndex = index1;
			let pos = 1;
			paint.drawLine(plot.lineColor, plot.lineWidth, null, mpx1, 0, mpx1, divHeight);
			let tSize = paint.textSize("1", chart.font);
			paint.drawText("1", chart.textColor, chart.font, mpx1, divHeight - tSize.cy);
			while (aIndex + fValue <= chart.lastVisibleIndex) {
				fValue = fibonacciValue(pos);
				let newIndex = aIndex + fValue;
				let newX = getChartX(chart, newIndex);
				paint.drawLine(plot.lineColor, plot.lineWidth, null, newX, 0, newX, divHeight);
				let tSize2 = paint.textSize(fValue.toString(), chart.font);
				paint.drawText(fValue.toString(), chart.textColor, chart.font, newX, divHeight - tSize2.cy);
				pos++;
			}
		}
		else if (plot.plotType == "SpeedResist") {
			paint.drawLine(plot.lineColor, plot.lineWidth, null, mpx1, mpy1, mpx2, mpy2);
			if (mpx1 != mpx2 && mpy1 != mpy2) {
				let firstP = new FCPoint(mpx2, mpy2 - (mpy2 - mpy1) / 3);
				let secondP = new FCPoint(mpx2, mpy2 - (mpy2 - mpy1) * 2 / 3);
				let startP = new FCPoint(mpx1, mpy1);
				let fK = 0, fB = 0, sK = 0, sB = 0;
				lineXY(chart, startP.x, startP.y, firstP.x, firstP.y, 0, 0);
				fK = chart.kChart;
				fB = chart.bChart;
				lineXY(chart, startP.x, startP.y, secondP.x, secondP.y, 0, 0);
				sK = chart.kChart;
				sB = chart.bChart;
				let newYF = 0, newYS = 0;
				let newX = 0;
				if (mpx2 > mpx1) {
					newYF = fK * (chart.size.cx - chart.rightVScaleWidth) + fB;
					newYS = sK * (chart.size.cx - chart.rightVScaleWidth) + sB;
					newX = (chart.size.cx - chart.rightVScaleWidth);
				}
				else {
					newYF = fB;
					newYS = sB;
					newX = chart.leftVScaleWidth;
				}
				paint.drawLine(plot.lineColor, plot.lineWidth, null, startP.x, startP.y, newX, newYF);
				paint.drawLine(plot.lineColor, plot.lineWidth, null, startP.x, startP.y, newX, newYS);
			}
		}
		else if (plot.plotType == "FiboFanline") {
			paint.drawLine(plot.lineColor, plot.lineWidth, null, mpx1, mpy1, mpx2, mpy2);
			if (mpx1 != mpx2 && mpy1 != mpy2) {
				let firstP = new FCPoint(mpx2, mpy2 - (mpy2 - mpy1) * 0.382);
				let secondP = new FCPoint(mpx2, mpy2 - (mpy2 - mpy1) * 0.5);
				let thirdP = new FCPoint(mpx2, mpy2 - (mpy2 - mpy1) * 0.618);
				let startP = new FCPoint(mpx1, mpy1);
				let listP : Array<FCPoint> = [];
				listP.push(firstP);
				listP.push(secondP);
				listP.push(thirdP);
				let listSize = listP.length;
				for (let j = 0; j < listSize; j++) {
					//获取直线参数
					lineXY(chart, startP.x, startP.y, listP[j].x, listP[j].y, 0, 0);
					let newX = 0;
					let newY = 0;
					if (mpx2 > mpx1) {
						newY = chart.kChart * (chart.size.cx - chart.rightVScaleWidth) + chart.bChart;
						newX = (chart.size.cx - chart.rightVScaleWidth);
					}
					else {
						newY = chart.bChart;
						newX = chart.leftVScaleWidth;
					}
					paint.drawLine(plot.lineColor, plot.lineWidth, null, startP.x, startP.y, newX, newY);
				}
			}
		}
		else if (plot.plotType == "LRLine") {
			paint.drawLine(plot.lineColor, plot.lineWidth, null, mpx1, mpy1, mpx2, mpy2);
		}
		else if (plot.plotType == "LRBand") {
			paint.drawLine(plot.lineColor, plot.lineWidth, null, mpx1, mpy1, mpx2, mpy2);
			getLRBandRange(chart, plot, chart.kChart, chart.bChart);
			mpy1 = getChartY(chart, 0, plot.value1 + chart.upSubValue);
			mpy2 = getChartY(chart, 0, plot.value2 + chart.upSubValue);
			paint.drawLine(plot.lineColor, plot.lineWidth, null, mpx1, mpy1, mpx2, mpy2);
			mpy1 = getChartY(chart, 0, plot.value1 - chart.downSubValue);
			mpy2 = getChartY(chart, 0, plot.value2 - chart.downSubValue);
			paint.drawLine(plot.lineColor, plot.lineWidth, null, mpx1, mpy1, mpx2, mpy2);
		}
		else if (plot.plotType == "LRChannel") {
			getLRBandRange(chart, plot, chart.kChart, chart.bChart);
			lineXY(chart, mpx1, mpy1, mpx2, mpy2, 0, 0);
			let rightX = chart.size.cx - chart.rightVScaleWidth;
			let rightY = rightX * chart.kChart + chart.bChart;
			paint.drawLine(plot.lineColor, plot.lineWidth, null, mpx1, mpy1, rightX, rightY);
			mpy1 = getChartY(chart, 0, plot.value1 + chart.upSubValue);
			mpy2 = getChartY(chart, 0, plot.value2 + chart.upSubValue);
			lineXY(chart, mpx1, mpy1, mpx2, mpy2, 0, 0);
			rightY = rightX * chart.kChart + chart.bChart;
			paint.drawLine(plot.lineColor, plot.lineWidth, null, mpx1, mpy1, rightX, rightY);
			mpy1 = getChartY(chart, 0, plot.value1 - chart.downSubValue);
			mpy2 = getChartY(chart, 0, plot.value2 - chart.downSubValue);
			lineXY(chart, mpx1, mpy1, mpx2, mpy2, 0, 0);
			rightY = rightX * chart.kChart + chart.bChart;
			paint.drawLine(plot.lineColor, plot.lineWidth, null, mpx1, mpy1, rightX, rightY);
		}
		else if (plot.plotType == "Segment") {
			paint.drawLine(plot.lineColor, plot.lineWidth, null, mpx1, mpy1, mpx2, mpy2);
		} else if (plot.plotType == "Ray") {
			lineXY(chart, mpx1, mpy1, mpx2, mpy2, 0, 0);
			if (chart.kChart != 0 || chart.bChart != 0) {
				let leftX = chart.leftVScaleWidth;
				let leftY = leftX * chart.kChart + chart.bChart;
				let rightX = chart.size.cx - chart.rightVScaleWidth;
				let rightY = rightX * chart.kChart + chart.bChart;
				if (mpx1 >= mpx2) {
					paint.drawLine(plot.lineColor, plot.lineWidth, null, leftX, leftY, mpx1, mpy1);
				} else {
					paint.drawLine(plot.lineColor, plot.lineWidth, null, mpx1, mpy1, rightX, rightY);
				}
			}
			//垂直时
			else {
				if (mpy1 >= mpy2) {
					paint.drawLine(plot.lineColor, plot.lineWidth, null, mpx1, mpy1, mpx1, 0);
				} else {
					paint.drawLine(plot.lineColor, plot.lineWidth, null, mpx1, mpy1, mpx1, divHeight);
				}
			}
		} else if (plot.plotType == "Triangle") {
			paint.drawLine(plot.lineColor, plot.lineWidth, null, mpx1, mpy1, mpx2, mpy2);
			paint.drawLine(plot.lineColor, plot.lineWidth, null, mpx2, mpy2, mpx3, mpy3);
			paint.drawLine(plot.lineColor, plot.lineWidth, null, mpx1, mpy1, mpx3, mpy3);
		}
		else if (plot.plotType == "SymmetricTriangle") {
			if (mpx2 != mpx1) {
				let a = (mpy2 - mpy1) / (mpx2 - mpx1);
				let b = mpy1 - a * mpx1;
				let c = -a;
				let d = mpy3 - c * mpx3;
				let leftX = chart.leftVScaleWidth;
				let leftY = leftX * a + b;
				let rightX = chart.size.cx - chart.rightVScaleWidth;
				let rightY = rightX * a + b;
				paint.drawLine(plot.lineColor, plot.lineWidth, null, leftX, leftY, rightX, rightY);
				leftY = leftX * c + d;
				rightY = rightX * c + d;
				paint.drawLine(plot.lineColor, plot.lineWidth, null, leftX, leftY, rightX, rightY);
			} else {
				paint.drawLine(plot.lineColor, plot.lineWidth, null, mpx1, 0, mpx1, divHeight);
				paint.drawLine(plot.lineColor, plot.lineWidth, null, mpx3, 0, mpx3, divHeight);
			}
		}
		else if (plot.plotType == "Rect") {
			let sX1 = Math.min(mpx1, mpx2);
			let sY1 = Math.min(mpy1, mpy2);
			let sX2 = Math.max(mpx1, mpx2);
			let sY2 = Math.max(mpy1, mpy2);
			paint.drawRect(plot.lineColor, plot.lineWidth, null, sX1, sY1, sX2, sY2);
		} else if (plot.plotType == "Cycle") {
			let r = Math.sqrt(Math.abs((mpx2 - mpx1) * (mpx2 - mpx1) + (mpy2 - mpy1) * (mpy2 - mpy1)));
			paint.drawEllipse(plot.lineColor, plot.lineWidth, null, mpx1 - r, mpy1 - r, mpx1 + r, mpy1 + r);
		} else if (plot.plotType == "CircumCycle") {
			ellipseOR(chart, mpx1, mpy1, mpx2, mpy2, mpx3, mpy3);
			paint.drawEllipse(plot.lineColor, plot.lineWidth, null, chart.oXChart - chart.rChart, chart.oYChart - chart.rChart, chart.oXChart + chart.rChart, chart.oYChart + chart.rChart);
		} else if (plot.plotType == "Ellipse") {
			let x1 = 0, y1 = 0, x2 = 0, y2 = 0;
			if (mpx1 <= mpx2) {
				x1 = mpx2;
				y1 = mpy2;
				x2 = mpx1;
				y2 = mpy1;
			} else {
				x1 = mpx1;
				y1 = mpy1;
				x2 = mpx2;
				y2 = mpy2;
			}
			let x = x1 - (x1 - x2);
			let y = 0;
			let width = (x1 - x2) * 2;
			let height = 0;
			if (y1 >= y2) {
				height = (y1 - y2) * 2;
			}
			else {
				height = (y2 - y1) * 2;
			}
			y = y2 - height / 2;
			paint.drawEllipse(plot.lineColor, plot.lineWidth, null, x, y, x + width, y + height);
		} else if (plot.plotType == "ParalleGram") {
			parallelogram(chart, mpx1, mpy1, mpx2, mpy2, mpx3, mpy3);
			paint.drawLine(plot.lineColor, plot.lineWidth, null, mpx1, mpy1, mpx2, mpy2);
			paint.drawLine(plot.lineColor, plot.lineWidth, null, mpx2, mpy2, mpx3, mpy3);
			paint.drawLine(plot.lineColor, plot.lineWidth, null, mpx3, mpy3, chart.x4Chart, chart.y4Chart);
			paint.drawLine(plot.lineColor, plot.lineWidth, null, chart.x4Chart, chart.y4Chart, mpx1, mpy1);
		} else if (plot.plotType == "BoxLine") {
			let sX1 = Math.min(mpx1, mpx2);
			let sY1 = Math.min(mpy1, mpy2);
			let sX2 = Math.max(mpx1, mpx2);
			let sY2 = Math.max(mpy1, mpy2);
			paint.drawRect(plot.lineColor, plot.lineWidth, null, sX1, sY1, sX2, sY2);
			let bSize = paint.textSize("COUNT:" + Math.abs(index2 - index1) + 1, chart.font);
			paint.drawText("COUNT:" + Math.abs(index2 - index1) + 1, chart.textColor, chart.font, sX1 + 2, sY1 + 2);
			let closeList : Array<number> = [];
			for (let j = index1; j <= index2; j++) {
				closeList.push(chart.data[j].close);
			}
			let avgClose = avgValue(closeList);
			let closeY = getChartY(chart, 0, avgClose);
			paint.drawLine(plot.lineColor, plot.lineWidth, [5, 5], sX1, closeY, sX2, closeY);
			let drawAvg = "AVG:" + avgClose.toFixed(chart.candleDigit);
			let tSize = paint.textSize(drawAvg, chart.font);
			paint.drawText(drawAvg, chart.textColor, chart.font, sX1 + 2, closeY - tSize.cy - 2);
		}
		else if (plot.plotType == "TironeLevels") {
			let sX1 = Math.min(mpx1, mpx2);
			let sY1 = Math.min(mpy1, mpy2);
			let sX2 = Math.max(mpx1, mpx2);
			let sY2 = Math.max(mpy1, mpy2);
			paint.drawLine(plot.lineColor, plot.lineWidth, null, sX1, sY1, sX2, sY1);
			paint.drawLine(plot.lineColor, plot.lineWidth, null, sX1, sY2, sX2, sY2);
			paint.drawLine(plot.lineColor, plot.lineWidth, [5, 5], sX1 + (sX2 - sX1) / 2, sY1, sX1 + (sX2 - sX1) / 2, sY2);
			let t1 = chart.nHighChart, t2 = chart.nHighChart - (chart.nHighChart - chart.nLowChart) / 3, t3 = chart.nHighChart - (chart.nHighChart - chart.nLowChart) / 2, t4 = chart.nHighChart - 2 * (chart.nHighChart - chart.nLowChart) / 3, t5 = chart.nLowChart;
			let tList : Array<number> = [];
			tList.push(t2);
			tList.push(t3);
			tList.push(t4);
			for (let j = 0; j < tList.length; j++) {
				let y = getChartY(chart, 0, tList[j]);
				//画直线
				paint.drawLine(plot.lineColor, plot.lineWidth, [5, 5], chart.leftVScaleWidth, y, chart.size.cx - chart.rightVScaleWidth, y);
				let str = tList[j].toFixed(chart.candleDigit);
				let tSize = paint.textSize(str, chart.font);
				paint.drawText(str, chart.textColor, chart.font, chart.leftVScaleWidth + 2, y - tSize.cy - 2);
			}
		}
		else if (plot.plotType == "QuadrantLines") {
			let sX1 = Math.min(mpx1, mpx2);
			let sY1 = Math.min(mpy1, mpy2);
			let sX2 = Math.max(mpx1, mpx2);
			let sY2 = Math.max(mpy1, mpy2);
			paint.drawLine(plot.lineColor, plot.lineWidth, null, sX1, sY1, sX2, sY1);
			paint.drawLine(plot.lineColor, plot.lineWidth, null, sX1, sY2, sX2, sY2);
			let t1 = chart.nHighChart, t2 = chart.nHighChart - (chart.nHighChart - chart.nLowChart) / 4, t3 = chart.nHighChart - (chart.nHighChart - chart.nLowChart) / 2, t4 = chart.nHighChart - 3 * (chart.nHighChart - chart.nLowChart) / 4, t5 = chart.nLowChart;
			let tList : Array<number> = [];
			tList.push(t2);
			tList.push(t3);
			tList.push(t4);
			for (let j = 0; j < tList.length; j++) {
				let y = getChartY(chart, 0, tList[j]);
				//画直线
				paint.drawLine(plot.lineColor, plot.lineWidth, null, sX1, y, sX2, y);
			}
		}
		else if (plot.plotType == "GoldenRatio") {
			let sX1 = Math.min(mpx1, mpx2);
			let sY1 = Math.min(mpy1, mpy2);
			let sX2 = Math.max(mpx1, mpx2);
			let sY2 = Math.max(mpy1, mpy2);
			let ranges : Array<number> = [];
			ranges.push(0);
			ranges.push(0.236);
			ranges.push(0.382);
			ranges.push(0.5);
			ranges.push(0.618);
			ranges.push(0.809);
			ranges.push(1);
			ranges.push(1.382);
			ranges.push(1.618);
			ranges.push(2);
			ranges.push(2.382);
			ranges.push(2.618);
			let minValue = Math.min(plot.value1, plot.value2);
			let maxValue = Math.max(plot.value1, plot.value2);
			for (let j = 0; j < ranges.length; j++) {
				let newY = sY1 <= sY2 ? sY1 + (sY2 - sY1) * ranges[j] : sY2 + (sY1 - sY2) * (1 - ranges[j]);
				paint.drawLine(plot.lineColor, plot.lineWidth, null, chart.leftVScaleWidth, newY, chart.size.cx - chart.rightVScaleWidth, newY);
				let newPoint = new FCPoint(0, newY);
				let value = getCandleDivValue(chart, newPoint);
				let str = value.toFixed(chart.candleDigit);
				let tSize = paint.textSize(str, chart.font);
				paint.drawText(str, chart.textColor, chart.font, chart.leftVScaleWidth + 2, newY - tSize.cy - 2);
			}
		}
	}

	paint.restore();
}

/*
* 选中直线
* chart: 图表
* mp:坐标
*/
function selectPlot(chart : FCChart, mp : FCPoint) : FCPlot | null {
	let sPlot : FCPlot | null = null;
	chart.startMovePlot = false;
	chart.selectPlotPoint = -1;
	for (let i = 0; i < chart.plots.length; i++) {
		let plot = chart.plots[i];
		let index1 = 0, index2 = 0, index3 = 0;
		let mpx1 = 0, mpy1 = 0, mpx2 = 0, mpy2 = 0, mpx3 = 0, mpy3 = 0;
		//检查关键点
		if (plot.key1 != 0) {
			index1 = getChartIndexByDate(chart, plot.key1);
			mpx1 = getChartX(chart, index1);
			mpy1 = getChartY(chart, 0, plot.value1);
			if (mp.x >= mpx1 - chart.plotPointSizeChart && mp.x <= mpx1 + chart.plotPointSizeChart && mp.y >= mpy1 - chart.plotPointSizeChart && mp.y <= mpy1 + chart.plotPointSizeChart) {
				sPlot = plot;
				chart.selectPlotPoint = 0;
				break;
			}
		}
		if (plot.key2 != 0) {
			index2 = getChartIndexByDate(chart, plot.key2);
			mpx2 = getChartX(chart, index2);
			mpy2 = getChartY(chart, 0, plot.value2);
			if (mp.x >= mpx2 - chart.plotPointSizeChart && mp.x <= mpx2 + chart.plotPointSizeChart && mp.y >= mpy2 - chart.plotPointSizeChart && mp.y <= mpy2 + chart.plotPointSizeChart) {
				sPlot = plot;
				chart.selectPlotPoint = 1;
				break;
			}
		}
		if (plot.key3 != 0) {
			index3 = getChartIndexByDate(chart, plot.key3);
			mpx3 = getChartX(chart, index3);
			mpy3 = getChartY(chart, 0, plot.value3);
			if (mp.x >= mpx3 - chart.plotPointSizeChart && mp.x <= mpx3 + chart.plotPointSizeChart && mp.y >= mpy3 - chart.plotPointSizeChart && mp.y <= mpy3 + chart.plotPointSizeChart) {
				sPlot = plot;
				chart.selectPlotPoint = 2;
				break;
			}
		}
		//判断其余部分的选中
		if (chart.selectPlotPoint == -1) {
			if (plot.plotType == "Line") {
				chart.startMovePlot = selectLine(chart, mp, mpx1, mpy1, mpx2, mpy2);
			}
			else if (plot.plotType == "ArrowSegment") {
				chart.startMovePlot = selectSegment(chart, mp, mpx1, mpy1, mpx2, mpy2);
			}
			else if (plot.plotType == "AngleLine") {
				chart.startMovePlot = selectLine(chart, mp, mpx1, mpy1, mpx2, mpy2);
				if (!chart.startMovePlot) {
					chart.startMovePlot = selectLine(chart, mp, mpx1, mpy1, mpx3, mpy3);
				}
			}
			else if (plot.plotType == "Parallel") {
				chart.startMovePlot = selectLine(chart, mp, mpx1, mpy1, mpx2, mpy2);
				if (!chart.startMovePlot) {
					lineXY(chart, mpx1, mpy1, mpx2, mpy2, 0, 0);
					let newB = mpy3 - chart.kChart * mpx3;
					if (mpx2 == mpx1) {
						if (mp.x >= mpx3 - chart.plotPointSizeChart && mp.x <= mpx3 + chart.plotPointSizeChart) {
							chart.startMovePlot = true;
						}
					} else {
						let newX1 = chart.leftVScaleWidth;
						let newY1 = newX1 * chart.kChart + newB;
						let newX2 = chart.size.cx - chart.rightVScaleWidth;
						let newY2 = newX2 * chart.kChart + newB;
						chart.startMovePlot = selectLine(chart, mp, newX1, newY1, newX2, newY2);
					}
				}
			}
			else if (plot.plotType == "LRLine") {
				chart.startMovePlot = selectSegment(chart, mp, mpx1, mpy1, mpx2, mpy2);
			}
			else if (plot.plotType == "Segment") {
				chart.startMovePlot = selectSegment(chart, mp, mpx1, mpy1, mpx2, mpy2);
			} else if (plot.plotType == "Ray") {
				chart.startMovePlot = selectRay(chart, mp, mpx1, mpy1, mpx2, mpy2);
			}
			else if (plot.plotType == "Triangle") {
				chart.startMovePlot = selectSegment(chart, mp, mpx1, mpy1, mpx2, mpy2);
				if (!chart.startMovePlot) {
					chart.startMovePlot = selectSegment(chart, mp, mpx2, mpy2, mpx3, mpy3);
				}
				if (!chart.startMovePlot) {
					chart.startMovePlot = selectSegment(chart, mp, mpx1, mpy1, mpx3, mpy3);
				}
			}
			else if (plot.plotType == "SymmetricTriangle") {
				if (mpx2 != mpx1) {
					let a = (mpy2 - mpy1) / (mpx2 - mpx1);
					let b = mpy1 - a * mpx1;
					let c = -a;
					let d = mpy3 - c * mpx3;
					let leftX = chart.leftVScaleWidth;
					let leftY = leftX * a + b;
					let rightX = chart.size.cx - chart.rightVScaleWidth;
					let rightY = rightX * a + b;
					chart.startMovePlot = selectSegment(chart, mp, leftX, leftY, rightX, rightY);
					if (!chart.startMovePlot) {
						leftY = leftX * c + d;
						rightY = rightX * c + d;
						chart.startMovePlot = selectSegment(chart, mp, leftX, leftY, rightX, rightY);
					}
				} else {
					let divHeight = getCandleDivHeight(chart);
					chart.startMovePlot = selectSegment(chart, mp, mpx1, 0, mpx1, divHeight);
					if (!chart.startMovePlot) {
						chart.startMovePlot = selectSegment(chart, mp, mpx3, 0, mpx3, divHeight);
					}
				}
			}
			else if (plot.plotType == "Rect") {
				let sX1 = Math.min(mpx1, mpx2);
				let sY1 = Math.min(mpy1, mpy2);
				let sX2 = Math.max(mpx1, mpx2);
				let sY2 = Math.max(mpy1, mpy2);
				chart.startMovePlot = selectSegment(chart, mp, sX1, sY1, sX2, sY1);
				if (!chart.startMovePlot) {
					chart.startMovePlot = selectSegment(chart, mp, sX2, sY1, sX2, sY2);
				}
				if (!chart.startMovePlot) {
					chart.startMovePlot = selectSegment(chart, mp, sX1, sY2, sX2, sY2);
				}
				if (!chart.startMovePlot) {
					chart.startMovePlot = selectSegment(chart, mp, sX1, sY1, sX1, sY2);
				}
			}
			else if (plot.plotType == "BoxLine") {
				let sX1 = Math.min(mpx1, mpx2);
				let sY1 = Math.min(mpy1, mpy2);
				let sX2 = Math.max(mpx1, mpx2);
				let sY2 = Math.max(mpy1, mpy2);
				chart.startMovePlot = selectSegment(chart, mp, sX1, sY1, sX2, sY1);
				if (!chart.startMovePlot) {
					chart.startMovePlot = selectSegment(chart, mp, sX2, sY1, sX2, sY2);
				}
				if (!chart.startMovePlot) {
					chart.startMovePlot = selectSegment(chart, mp, sX1, sY2, sX2, sY2);
				}
				if (!chart.startMovePlot) {
					chart.startMovePlot = selectSegment(chart, mp, sX1, sY1, sX1, sY2);
				}
			}
			else if (plot.plotType == "TironeLevels") {
				let sX1 = Math.min(mpx1, mpx2);
				let sY1 = Math.min(mpy1, mpy2);
				let sX2 = Math.max(mpx1, mpx2);
				let sY2 = Math.max(mpy1, mpy2);
				chart.startMovePlot = selectSegment(chart, mp, sX1, sY1, sX2, sY1);
				if (!chart.startMovePlot) {
					chart.startMovePlot = selectSegment(chart, mp, sX1, sY2, sX2, sY2);
				}
			}
			else if (plot.plotType == "QuadrantLines") {
				let sX1 = Math.min(mpx1, mpx2);
				let sY1 = Math.min(mpy1, mpy2);
				let sX2 = Math.max(mpx1, mpx2);
				let sY2 = Math.max(mpy1, mpy2);
				chart.startMovePlot = selectSegment(chart, mp, sX1, sY1, sX2, sY1);
				if (!chart.startMovePlot) {
					chart.startMovePlot = selectSegment(chart, mp, sX1, sY2, sX2, sY2);
				}
			} else if (plot.plotType == "GoldenRatio") {
				let sX1 = Math.min(mpx1, mpx2);
				let sY1 = Math.min(mpy1, mpy2);
				let sX2 = Math.max(mpx1, mpx2);
				let sY2 = Math.max(mpy1, mpy2);
				let ranges : Array<number> = [];
				ranges.push(0);
				ranges.push(0.236);
				ranges.push(0.382);
				ranges.push(0.5);
				ranges.push(0.618);
				ranges.push(0.809);
				ranges.push(1);
				ranges.push(1.382);
				ranges.push(1.618);
				ranges.push(2);
				ranges.push(2.382);
				ranges.push(2.618);
				let minValue = Math.min(plot.value1, plot.value2);
				let maxValue = Math.max(plot.value1, plot.value2);
				for (let j = 0; j < ranges.length; j++) {
					let newY = sY1 <= sY2 ? sY1 + (sY2 - sY1) * ranges[j] : sY2 + (sY1 - sY2) * (1 - ranges[j]);
					chart.startMovePlot = selectSegment(chart, mp, chart.leftVScaleWidth, newY, chart.size.cx - chart.rightVScaleWidth, newY);
					if (chart.startMovePlot) {
						break;
					}
				}
			}
			else if (plot.plotType == "Cycle") {
				let r = Math.sqrt(Math.abs((mpx2 - mpx1) * (mpx2 - mpx1) + (mpy2 - mpy1) * (mpy2 - mpy1)));
				let round = (mp.x - mpx1) * (mp.x - mpx1) + (mp.y - mpy1) * (mp.y - mpy1);
				if (round / (r * r) >= 0.9 && round / (r * r) <= 1.1) {
					chart.startMovePlot = true;
				}
			} else if (plot.plotType == "CircumCycle") {
				ellipseOR(chart, mpx1, mpy1, mpx2, mpy2, mpx3, mpy3);
				let round = (mp.x - chart.oXChart) * (mp.x - chart.oXChart) + (mp.y - chart.oYChart) * (mp.y - chart.oYChart);
				if (round / (chart.rChart * chart.rChart) >= 0.9 && round / (chart.rChart * chart.rChart) <= 1.1) {
					chart.startMovePlot = true;
				}
			}
			else if (plot.plotType == "Ellipse") {
				let x1 = 0, y1 = 0, x2 = 0, y2 = 0;
				if (mpx1 <= mpx2) {
					x1 = mpx2;
					y1 = mpy2;
					x2 = mpx1;
					y2 = mpy1;
				} else {
					x1 = mpx1;
					y1 = mpy1;
					x2 = mpx2;
					y2 = mpy2;
				}
				let x = x1 - (x1 - x2);
				let y = 0;
				let width = (x1 - x2) * 2;
				let height = 0;
				if (y1 >= y2) {
					height = (y1 - y2) * 2;
				}
				else {
					height = (y2 - y1) * 2;
				}
				y = y2 - height / 2;
				let a = width / 2;
				let b = height / 2;
				chart.startMovePlot = ellipseHasPoint(mp.x, mp.y, x + (width / 2), y + (height / 2), a, b);
			} else if (plot.plotType == "LRBand") {
				chart.startMovePlot = selectSegment(chart, mp, mpx1, mpy1, mpx2, mpy2);
				if (!chart.startMovePlot) {
					let list : Array<number> = [];
					let minIndex = Math.min(index1, index2);
					let maxIndex = Math.max(index1, index2);
					for (let j = minIndex; j <= maxIndex; j++) {
						list.push(chart.data[j].close);
					}
					linearRegressionEquation(chart, list);
					getLRBandRange(chart, plot, chart.kChart, chart.bChart);
					mpy1 = getChartY(chart, 0, plot.value1 + chart.upSubValue);
					mpy2 = getChartY(chart, 0, plot.value2 + chart.upSubValue);
					chart.startMovePlot = selectSegment(chart, mp, mpx1, mpy1, mpx2, mpy2);
					if (!chart.startMovePlot) {
						mpy1 = getChartY(chart, 0, plot.value1 - chart.downSubValue);
						mpy2 = getChartY(chart, 0, plot.value2 - chart.downSubValue);
						chart.startMovePlot = selectSegment(chart, mp, mpx1, mpy1, mpx2, mpy2);
					}
				}
			} else if (plot.plotType == "LRChannel") {
				lineXY(chart, mpx1, mpy1, mpx2, mpy2, 0, 0);
				let rightX = chart.size.cx - chart.rightVScaleWidth;
				let rightY = rightX * chart.kChart + chart.bChart;
				chart.startMovePlot = selectSegment(chart, mp, mpx1, mpy1, rightX, rightY);
				if (!chart.startMovePlot) {
					let list : Array<number> = [];
					let minIndex = Math.min(index1, index2);
					let maxIndex = Math.max(index1, index2);
					for (let j = minIndex; j <= maxIndex; j++) {
						list.push(chart.data[j].close);
					}
					linearRegressionEquation(chart, list);
					getLRBandRange(chart, plot, chart.kChart, chart.bChart);
					mpy1 = getChartY(chart, 0, plot.value1 + chart.upSubValue);
					mpy2 = getChartY(chart, 0, plot.value2 + chart.upSubValue);
					lineXY(chart, mpx1, mpy1, mpx2, mpy2, 0, 0);
					rightY = rightX * chart.kChart + chart.bChart;
					chart.startMovePlot = selectSegment(chart, mp, mpx1, mpy1, rightX, rightY);
					if (!chart.startMovePlot) {
						mpy1 = getChartY(chart, 0, plot.value1 - chart.downSubValue);
						mpy2 = getChartY(chart, 0, plot.value2 - chart.downSubValue);
						lineXY(chart, mpx1, mpy1, mpx2, mpy2, 0, 0);
						rightY = rightX * chart.kChart + chart.bChart;
						chart.startMovePlot = selectSegment(chart, mp, mpx1, mpy1, rightX, rightY);
					}
				}
			} else if (plot.plotType == "ParalleGram") {
				parallelogram(chart, mpx1, mpy1, mpx2, mpy2, mpx3, mpy3);
				chart.startMovePlot = selectSegment(chart, mp, mpx1, mpy1, mpx2, mpy2);
				if (!chart.startMovePlot) {
					chart.startMovePlot = selectSegment(chart, mp, mpx2, mpy2, mpx3, mpy3);
					if (!chart.startMovePlot) {
						chart.startMovePlot = selectSegment(chart, mp, mpx3, mpy3, chart.x4Chart, chart.y4Chart);
						if (!chart.startMovePlot) {
							chart.startMovePlot = selectSegment(chart, mp, chart.x4Chart, chart.y4Chart, mpx1, mpy1);
						}
					}
				}
			}
			else if (plot.plotType == "SpeedResist") {
				chart.startMovePlot = selectSegment(chart, mp, mpx1, mpy1, mpx2, mpy2);
				if (!chart.startMovePlot) {
					if (mpx1 != mpx2 && mpy1 != mpy2) {
						let firstP = new FCPoint(mpx2, mpy2 - (mpy2 - mpy1) / 3);
						let secondP = new FCPoint(mpx2, mpy2 - (mpy2 - mpy1) * 2 / 3);
						let startP = new FCPoint(mpx1, mpy1);
						let fK = 0, fB = 0, sK = 0, sB = 0;
						lineXY(chart, startP.x, startP.y, firstP.x, firstP.y, 0, 0);
						fK = chart.kChart;
						fB = chart.bChart;
						lineXY(chart, startP.x, startP.y, secondP.x, secondP.y, 0, 0);
						sK = chart.kChart;
						sB = chart.bChart;
						let newYF = 0, newYS = 0;
						let newX = 0;
						if (mpx2 > mpx1) {
							newYF = fK * (chart.size.cx - chart.rightVScaleWidth) + fB;
							newYS = sK * (chart.size.cx - chart.rightVScaleWidth) + sB;
							newX = (chart.size.cx - chart.rightVScaleWidth);
						}
						else {
							newYF = fB;
							newYS = sB;
							newX = chart.leftVScaleWidth;
						}
						chart.startMovePlot = selectSegment(chart, mp, startP.x, startP.y, newX, newYF);
						if (!chart.startMovePlot) {
							chart.startMovePlot = selectSegment(chart, mp, startP.x, startP.y, newX, newYS);
						}
					}
				}
			} else if (plot.plotType == "FiboFanline") {
				chart.startMovePlot = selectSegment(chart, mp, mpx1, mpy1, mpx2, mpy2);
				if (!chart.startMovePlot) {
					if (mpx1 != mpx2 && mpy1 != mpy2) {
						let firstP = new FCPoint(mpx2, mpy2 - (mpy2 - mpy1) * 0.382);
						let secondP = new FCPoint(mpx2, mpy2 - (mpy2 - mpy1) * 0.5);
						let thirdP = new FCPoint(mpx2, mpy2 - (mpy2 - mpy1) * 0.618);
						let startP = new FCPoint(mpx1, mpy1);
						let listP : Array<FCPoint> = [];
						listP.push(firstP);
						listP.push(secondP);
						listP.push(thirdP);
						let listSize = listP.length;
						for (let j = 0; j < listSize; j++) {
							lineXY(chart, startP.x, startP.y, listP[j].x, listP[j].y, 0, 0);
							let newX = 0;
							let newY = 0;
							if (mpx2 > mpx1) {
								newY = chart.kChart * (chart.size.cx - chart.rightVScaleWidth) + chart.bChart;
								newX = (chart.size.cx - chart.rightVScaleWidth);
							}
							else {
								newY = chart.bChart;
								newX = chart.leftVScaleWidth;
							}
							chart.startMovePlot = selectSegment(chart, mp, startP.x, startP.y, newX, newY);
							if (chart.startMovePlot) {
								break;
							}
						}
					}
				}
			}
			else if (plot.plotType == "FiboTimezone") {
				let fValue = 1;
				let aIndex = index1;
				let pos = 1;
				let divHeight = getCandleDivHeight(chart);
				chart.startMovePlot = selectSegment(chart, mp, mpx1, 0, mpx1, divHeight);
				if (!chart.startMovePlot) {
					while (aIndex + fValue <= chart.lastVisibleIndex) {
						fValue = fibonacciValue(pos);
						let newIndex = aIndex + fValue;
						let newX = getChartX(chart, newIndex);
						chart.startMovePlot = selectSegment(chart, mp, newX, 0, newX, divHeight);
						if (chart.startMovePlot) {
							break;
						}
						pos++;
					}
				}
			}
			else if (plot.plotType == "Percent") {
				let list = getPercentParams(mpy1, mpy2);
				for (let j = 0; j < list.length; j++) {
					chart.startMovePlot = selectSegment(chart, mp, chart.leftVScaleWidth, list[j], chart.size.cx - chart.rightVScaleWidth, list[j]);
					if (chart.startMovePlot) {
						break;
					}
				}
			}
			if (chart.startMovePlot) {
				sPlot = plot;
				plot.startKey1 = plot.key1;
				plot.startValue1 = plot.value1;
				plot.startKey2 = plot.key2;
				plot.startValue2 = plot.value2;
				plot.startKey3 = plot.key3;
				plot.startValue3 = plot.value3;
				break;
			}
		}
	}
	return sPlot;
}

/*
* 计算线性回归上下限
* chart:图表
* plot:画线
* a:直线k
* b:直线b
*/
function getLRBandRange(chart : FCChart, plot : FCPlot, a : number, b : number) {
	let bIndex = getChartIndexByDate(chart, plot.key1);
	let eIndex = getChartIndexByDate(chart, plot.key2);
	let tempBIndex = Math.min(bIndex, eIndex);
	let tempEIndex = Math.max(bIndex, eIndex);
	bIndex = tempBIndex;
	eIndex = tempEIndex;
	let upList : Array<number> = [];
	let downList : Array<number> = [];
	for (let i = bIndex; i <= eIndex; i++) {
		let high = chart.data[i].high;
		let low = chart.data[i].low;
		let midValue = (i - bIndex + 1) * a + b;
		upList.push(high - midValue);
		downList.push(midValue - low);
	}
	chart.upSubValue = maxValue(upList);
	chart.downSubValue = maxValue(downList);
}

/*
* 根据位置计算索引
* chart:图表
* mp:坐标
*/
function getChartIndex(chart : FCChart, mp : FCPoint) : number {
	if (chart.data != null && chart.data.length == 0) {
		return -1;
	}
	if (mp.x <= 0) {
		return 0;
	}
	let intX = Math.floor(mp.x - chart.leftVScaleWidth - chart.hScalePixel);
	let index = Math.floor(chart.firstVisibleIndex + intX / chart.hScalePixel);
	if (intX % chart.hScalePixel != 0) {
		index++;
	}
	if (index < 0) {
		index = 0;
	} else if (chart.data != null && index > chart.data.length - 1) {
		index = chart.data.length - 1;
	}
	return index;
}

/*
* 获取最大显示记录条数
* chart:图表
* hScalePixel:间隔
* pureH:横向距离
*/
function getChartMaxVisibleCount(chart : FCChart, hScalePixel : number, pureH : number) : number {
	let count = Math.floor((pureH - hScalePixel) / hScalePixel);
	if (count < 0) {
		count = 0;
	}
	return count;
}

/*
* 获取图表层的高度
* chart:图表
*/
function getCandleDivHeight(chart : FCChart) : number {
	let height = chart.size.cy - chart.hScaleHeight;
	if (height > 0) {
		return height * chart.candleDivPercent;
	} else {
		return 0;
	}
}

/*
* 获取成交量层的高度
* chart:图表
*/
function getVolDivHeight(chart : FCChart) : number {
	let height = chart.size.cy - chart.hScaleHeight;
	if (height > 0) {
		return height * chart.volDivPercent;
	} else {
		return 0;
	}
}

/*
* 获取指标层的高度
* chart:图表
*/
function getIndDivHeight(chart : FCChart) : number {
	let height = chart.size.cy - chart.hScaleHeight;
	if (height > 0) {
		return height * chart.indDivPercent;
	} else {
		return 0;
	}
}

/*
* 获取指标层2的高度
* chart:图表
*/
function getIndDivHeight2(chart : FCChart) : number {
	let height = chart.size.cy - chart.hScaleHeight;
	if (height > 0) {
		return height * chart.indDivPercent2;
	} else {
		return 0;
	}
}

/*
* 获取横向工作区
* chart:图表
*/
function getChartWorkAreaWidth(chart : FCChart) : number {
	return chart.size.cx - chart.leftVScaleWidth - chart.rightVScaleWidth - chart.rightSpace;
}

/*
* 根据索引获取横坐标
* chart:图表
* index:索引
*/
function getChartX(chart : FCChart, index : number) : number {
	return chart.leftVScaleWidth + (index - chart.firstVisibleIndex) * chart.hScalePixel + chart.hScalePixel;
}

/*
* 根据日期获取索引
* chart:图表
* date:日期
*/
function getChartIndexByDate(chart : FCChart, date : number) : number {
	let index = -1;
	for (let i = 0; i < chart.data.length; i++) {
		if (chart.data[i].date == date) {
			index = i;
			break;
		}
	}
	return index;
}

/*
* 根据索引获取日期
* chart:图表
* index:索引
*/
function getChartDateByIndex(chart : FCChart, index : number) : number {
	let date = 0;
	if (index >= 0 && index < chart.data.length) {
		date = chart.data[index].date;
	}
	return date;
}

/*
* 计算数值在层中的位置
* chart:图表
* divIndex:所在层
* chart:数值
*/
function getChartY(chart : FCChart, divIndex : number, value : number) : number {
	if (divIndex == 0) {
		if (chart.candleMax > chart.candleMin) {
			let cValue = value, cMax = chart.candleMax, cMin = chart.candleMin;
			if (chart.vScaleType != "standard") {
				if (cValue > 0) {
					cValue = Math.log10(cValue);
				} else if (cValue < 0) {
					cValue = -Math.log10(Math.abs(cValue));
				}
				if (cMax > 0) {
					cMax = Math.log10(cMax);
				} else if (cMax < 0) {
					cMax = -Math.log10(Math.abs(cMax));
				}
				if (cMin > 0) {
					cMin = Math.log10(cMin);
				} else if (cMin < 0) {
					cMin = -Math.log10(Math.abs(cMin));
				}
			}
			let rate = (cValue - cMin) / (cMax - cMin);
			let divHeight = getCandleDivHeight(chart);
			return divHeight - chart.candlePaddingBottom - (divHeight - chart.candlePaddingTop - chart.candlePaddingBottom) * rate;
		} else {
			return 0;
		}
	} else if (divIndex == 1) {
		if (chart.volMax > chart.volMin) {
			let rate = (value - chart.volMin) / (chart.volMax - chart.volMin);
			let candleHeight = getCandleDivHeight(chart);
			let volHeight = getVolDivHeight(chart);
			return candleHeight + volHeight - chart.volPaddingBottom - (volHeight - chart.volPaddingTop - chart.volPaddingBottom) * rate;
		} else {
			return 0;
		}
	} else if (divIndex == 2) {
		if (chart.indMax > chart.indMin) {
			let rate = (value - chart.indMin) / (chart.indMax - chart.indMin);
			let candleHeight = getCandleDivHeight(chart);
			let volHeight = getVolDivHeight(chart);
			let indHeight = getIndDivHeight(chart);
			return candleHeight + volHeight + indHeight - chart.indPaddingBottom - (indHeight - chart.indPaddingTop - chart.indPaddingBottom) * rate;
		} else {
			return 0;
		}
	}
	else if (divIndex == 3) {
		if (chart.indMax2 > chart.indMin2) {
			let rate = (value - chart.indMin2) / (chart.indMax2 - chart.indMin2);
			let candleHeight = getCandleDivHeight(chart);
			let volHeight = getVolDivHeight(chart);
			let indHeight = getIndDivHeight(chart);
			let indHeight2 = getIndDivHeight2(chart);
			return candleHeight + volHeight + indHeight + indHeight2 - chart.indPaddingBottom2 - (indHeight2 - chart.indPaddingTop2 - chart.indPaddingBottom2) * rate;
		} else {
			return 0;
		}
	}
	return 0;
}

/*
* 计算数值在层中的右轴位置
* chart:图表
* divIndex:所在层
* chart:数值
*/
function getChartYInRight(chart : FCChart, divIndex : number, value : number) : number {
	if (divIndex == 0) {
		if (chart.candleMaxRight > chart.candleMinRight) {
			let cValue = value, cMax = chart.candleMaxRight, cMin = chart.candleMinRight;
			if (chart.vScaleType != "standard") {
				if (cValue > 0) {
					cValue = Math.log10(cValue);
				} else if (cValue < 0) {
					cValue = -Math.log10(Math.abs(cValue));
				}
				if (cMax > 0) {
					cMax = Math.log10(cMax);
				} else if (cMax < 0) {
					cMax = -Math.log10(Math.abs(cMax));
				}
				if (cMin > 0) {
					cMin = Math.log10(cMin);
				} else if (cMin < 0) {
					cMin = -Math.log10(Math.abs(cMin));
				}
			}
			let rate = (cValue - cMin) / (cMax - cMin);
			let divHeight = getCandleDivHeight(chart);
			return divHeight - chart.candlePaddingBottom - (divHeight - chart.candlePaddingTop - chart.candlePaddingBottom) * rate;
		} else {
			return 0;
		}
	} else if (divIndex == 1) {
		if (chart.volMaxRight > chart.volMinRight) {
			let rate = (value - chart.volMinRight) / (chart.volMaxRight - chart.volMinRight);
			let candleHeight = getCandleDivHeight(chart);
			let volHeight = getVolDivHeight(chart);
			return candleHeight + volHeight - chart.volPaddingBottom - (volHeight - chart.volPaddingTop - chart.volPaddingBottom) * rate;
		} else {
			return 0;
		}
	} else if (divIndex == 2) {
		if (chart.indMaxRight > chart.indMinRight) {
			let rate = (value - chart.indMinRight) / (chart.indMaxRight - chart.indMinRight);
			let candleHeight = getCandleDivHeight(chart);
			let volHeight = getVolDivHeight(chart);
			let indHeight = getIndDivHeight(chart);
			return candleHeight + volHeight + indHeight - chart.indPaddingBottom - (indHeight - chart.indPaddingTop - chart.indPaddingBottom) * rate;
		} else {
			return 0;
		}
	}
	else if (divIndex == 3) {
		if (chart.indMax2Right > chart.indMin2Right) {
			let rate = (value - chart.indMin2Right) / (chart.indMax2Right - chart.indMin2Right);
			let candleHeight = getCandleDivHeight(chart);
			let volHeight = getVolDivHeight(chart);
			let indHeight = getIndDivHeight(chart);
			let indHeight2 = getIndDivHeight2(chart);
			return candleHeight + volHeight + indHeight + indHeight2 - chart.indPaddingBottom2 - (indHeight2 - chart.indPaddingTop2 - chart.indPaddingBottom2) * rate;
		} else {
			return 0;
		}
	}
	return 0;
}

/*
* 根据坐标获取对应的值
* chart:图表
* point:坐标
*/
function getChartValue(chart : FCChart, point : FCPoint) : number {
	let candleHeight = getCandleDivHeight(chart);
	let volHeight = getVolDivHeight(chart);
	let indHeight = getIndDivHeight(chart);
	let indHeight2 = getIndDivHeight(chart);
	if (point.y <= candleHeight) {
		let rate = (candleHeight - chart.candlePaddingBottom - point.y) / (candleHeight - chart.candlePaddingTop - chart.candlePaddingBottom);
		let cMin = chart.candleMin, cMax = chart.candleMax;
		if (chart.vScaleType != "standard") {
			if (cMax > 0) {
				cMax = Math.log10(cMax);
			} else if (cMax < 0) {
				cMax = -Math.log10(Math.abs(cMax));
			}
			if (cMin > 0) {
				cMin = Math.log10(cMin);
			} else if (cMin < 0) {
				cMin = -Math.log10(Math.abs(cMin));
			}
		}
		let result = cMin + (cMax - cMin) * rate;
		if (chart.vScaleType != "standard") {
			return Math.pow(10, result);
		} else {
			return result;
		}
	}
	else if (point.y > candleHeight && point.y <= candleHeight + volHeight) {
		let rate = (volHeight - chart.volPaddingBottom - (point.y - candleHeight)) / (volHeight - chart.volPaddingTop - chart.volPaddingBottom);
		return chart.volMin + (chart.volMax - chart.volMin) * rate;
	} else if (point.y > candleHeight + volHeight && point.y <= candleHeight + volHeight + indHeight) {
		let rate = (indHeight - chart.indPaddingBottom - (point.y - candleHeight - volHeight)) / (indHeight - chart.indPaddingTop - chart.indPaddingBottom);
		return chart.indMin + (chart.indMax - chart.indMin) * rate;
	} else if (point.y > candleHeight + volHeight + indHeight && point.y <= candleHeight + volHeight + indHeight + indHeight2) {
		let rate = (indHeight2 - chart.indPaddingBottom2 - (point.y - candleHeight - volHeight - indHeight)) / (indHeight2 - chart.indPaddingTop2 - chart.indPaddingBottom2);
		return chart.indMin2 + (chart.indMax2 - chart.indMin2) * rate;
	}
	return 0;
}

/*
* 根据坐标获取对应的值
* chart:图表
* point:坐标
*/
function getCandleDivValue(chart : FCChart, point : FCPoint) : number {
	let candleHeight = getCandleDivHeight(chart);
	let rate = (candleHeight - chart.candlePaddingBottom - point.y) / (candleHeight - chart.candlePaddingTop - chart.candlePaddingBottom);
	let cMin = chart.candleMin, cMax = chart.candleMax;
	if (chart.vScaleType != "standard") {
		if (cMax > 0) {
			cMax = Math.log10(cMax);
		} else if (cMax < 0) {
			cMax = -Math.log10(Math.abs(cMax));
		}
		if (cMin > 0) {
			cMin = Math.log10(cMin);
		} else if (cMin < 0) {
			cMin = -Math.log10(Math.abs(cMin));
		}
	}
	let result = cMin + (cMax - cMin) * rate;
	if (chart.vScaleType != "standard") {
		return Math.pow(10, result);
	} else {
		return result;
	}
}

/*
* 检查最后可见索引
* chart:图表
*/
function checkChartLastVisibleIndex(chart : FCChart) {
	if (chart.lastVisibleIndex > chart.data.length - 1) {
		chart.lastVisibleIndex = chart.data.length - 1;
	}
	if (chart.data.length > 0 && chart.lastVisibleIndex != -1) {
		chart.lastVisibleKey = chart.data[chart.lastVisibleIndex].date;
		if (chart.lastVisibleIndex == chart.data.length - 1) {
			chart.lastRecordIsVisible = true;
		} else {
			chart.lastRecordIsVisible = false;
		}
	} else {
		chart.lastVisibleKey = 0;
		chart.lastRecordIsVisible = true;
	}
}

/*
* 自动设置首先可见和最后可见的记录号
* chart:图表
*/
function resetChartVisibleRecord(chart : FCChart) {
	let rowsCount = chart.data.length;
	let workingAreaWidth = getChartWorkAreaWidth(chart);
	if (chart.autoFillHScale) {
		if (workingAreaWidth > 0 && rowsCount > 0) {
			chart.hScalePixel = workingAreaWidth / rowsCount;
			chart.firstVisibleIndex = 0;
			chart.lastVisibleIndex = rowsCount - 1;
		}
	} else {
		let maxVisibleRecord = getChartMaxVisibleCount(chart, chart.hScalePixel, workingAreaWidth);
		//没数据时重置
		if (rowsCount == 0) {
			chart.firstVisibleIndex = -1;
			chart.lastVisibleIndex = -1;
		} else {
			//数据不足一屏时
			if (rowsCount < maxVisibleRecord) {
				chart.lastVisibleIndex = rowsCount - 1;
				chart.firstVisibleIndex = 0;
			}
			//数据超过一屏时
			else {
				//显示中间的数据时
				if (chart.firstVisibleIndex != -1 && chart.lastVisibleIndex != -1 && !chart.lastRecordIsVisible) {
					let index = getChartIndexByDate(chart, chart.lastVisibleKey);
					if (index != -1) {
						chart.lastVisibleIndex = index;
					}
					chart.firstVisibleIndex = chart.lastVisibleIndex - maxVisibleRecord + 1;
					if (chart.firstVisibleIndex < 0) {
						chart.firstVisibleIndex = 0;
						chart.lastVisibleIndex = chart.firstVisibleIndex + maxVisibleRecord;
						checkChartLastVisibleIndex(chart);
					}
				} else {
					//第一条或最后一条数据被显示时
					chart.lastVisibleIndex = rowsCount - 1;
					chart.firstVisibleIndex = chart.lastVisibleIndex - maxVisibleRecord + 1;
					if (chart.firstVisibleIndex > chart.lastVisibleIndex) {
						chart.firstVisibleIndex = chart.lastVisibleIndex;
					}
				}
			}
		}
	}
}

/*
* 设置可见索引
* chart:图表
* firstVisibleIndex:起始索引
* lastVisibleIndex:结束索引
*/
function setChartVisibleIndex(chart : FCChart, firstVisibleIndex : number, lastVisibleIndex : number) {
	let xScalePixel = getChartWorkAreaWidth(chart) / (lastVisibleIndex - firstVisibleIndex + 1);
	if (xScalePixel < 1000000) {
		chart.firstVisibleIndex = firstVisibleIndex;
		chart.lastVisibleIndex = lastVisibleIndex;
		//设置最后一条记录是否可见
		if (lastVisibleIndex != chart.data.length - 1) {
			chart.lastRecordIsVisible = false;
		} else {
			chart.lastRecordIsVisible = true;
		}
		chart.hScalePixel = xScalePixel;
		checkChartLastVisibleIndex(chart);
	}
}

/*
* 清除图形
* chart:图表
* paint:绘图对象
* clipRect:裁剪区域
*/
function drawChart(chart : FCChart, paint : FCPaint, clipRect : FCRect) {
	if (chart.backColor != null && chart.backColor != "none") {
		paint.fillRect(chart.backColor, 0, 0, chart.size.cx, chart.size.cy);
	}
	if (paint.onPaintChartScale != null) {
		paint.onPaintChartScale!(chart, paint, clipRect);
	} else {
		drawChartScale(chart, paint, clipRect);
	}
	if (paint.onPaintChartStock != null) {
		paint.onPaintChartStock!(chart, paint, clipRect);
	} else {
		drawChartStock(chart, paint, clipRect);
	}
	if (paint.onPaintChartPlot != null) {
		paint.onPaintChartPlot!(chart, paint, clipRect);
	} else {
		drawChartPlot(chart, paint, clipRect);
	}
	if (paint.onPaintChartCrossLine != null) {
		paint.onPaintChartCrossLine!(chart, paint, clipRect);
	} else {
		drawChartCrossLine(chart, paint, clipRect);
	}
	if (chart.borderColor != null) {
		paint.drawRect(chart.borderColor, chart.lineWidthChart, null, 0, 0, chart.size.cx, chart.size.cy);
	}
}

/*
* 计算坐标轴
* min:最小值
* max:最大值
* yLen:长度
* maxSpan:最大间隔
* minSpan:最小间隔
* defCount:数量
*/
function chartGridScale(chart : FCChart, min : number, max : number, yLen : number, maxSpan : number, minSpan : number, defCount : number) : number {
	let sub = max - min;
	let nMinCount = Math.floor(Math.ceil(yLen / maxSpan));
	let nMaxCount = Math.floor(Math.floor(yLen / minSpan));
	let nCount = defCount;
	let logStep = sub / nCount;
	let start = false;
	let divisor = 0;
	let i = 0, nTemp = 0;
	chart.gridStepChart = 0;
	chart.gridDigitChart = 0;
	nCount = Math.max(nMinCount, nCount);
	nCount = Math.min(nMaxCount, nCount);
	nCount = Math.max(nCount, 1);
	for (i = 15; i >= -6; i--) {
		divisor = Math.pow(10.0, i);
		if (divisor < 1) {
			chart.gridDigitChart++;
		}
		nTemp = Math.floor(Math.floor(logStep / divisor));
		if (start) {
			if (nTemp < 4) {
				if (chart.gridDigitChart > 0) {
					chart.gridDigitChart--;
				}
			} else if (nTemp >= 4 && nTemp <= 6) {
				nTemp = 5;
				chart.gridStepChart += nTemp * divisor;
			} else {
				chart.gridStepChart += 10 * divisor;
				if (chart.gridDigitChart > 0) {
					chart.gridDigitChart--;
				}
			}
			break;
		} else if (nTemp > 0) {
			chart.gridStepChart = nTemp * divisor + chart.gridStepChart;
			logStep -= chart.gridStepChart;
			start = true;
		}
	}
	return 0;
}

/*
* 缩小
* chart:图表
*/
function zoomOutChart(chart : FCChart) {
	if (!chart.autoFillHScale) {
		let hScalePixel = chart.hScalePixel;
		let oldX = getChartX(chart, chart.crossStopIndex);
		let pureH = getChartWorkAreaWidth(chart);
		let oriMax = -1, max = -1, deal = 0;
		let dataCount = chart.data.length;
		let findex = chart.firstVisibleIndex, lindex = chart.lastVisibleIndex;
		if (hScalePixel < pureH) {
			oriMax = getChartMaxVisibleCount(chart, hScalePixel, pureH);
			if (dataCount < oriMax) {
				deal = 1;
			}
			if (hScalePixel > 3) {
				hScalePixel += 1;
			} else {
				if (hScalePixel == 1) {
					hScalePixel = 2;
				} else {
					hScalePixel = hScalePixel * 1.5;
					if (hScalePixel > 3) {
						hScalePixel = Math.floor(hScalePixel);
					}
				}
			}
			max = getChartMaxVisibleCount(chart, hScalePixel, pureH);
			if (dataCount >= max) {
				if (deal == 1) {
					lindex = dataCount - 1;
				}
				findex = lindex - max + 1;
				if (findex < 0) {
					findex = 0;
				}
			}
		}
		chart.hScalePixel = hScalePixel;
		chart.firstVisibleIndex = findex;
		chart.lastVisibleIndex = lindex;
		if (chart.showCrossLine) {
			let newX = getChartX(chart, chart.crossStopIndex);
			if (newX > oldX) {
				while (chart.lastVisibleIndex < chart.data.length - 1) {
					chart.firstVisibleIndex++;
					chart.lastVisibleIndex++;
					newX = getChartX(chart, chart.crossStopIndex);
					if (newX <= oldX) {
						break;
					}
				}

			}
			else if (newX < oldX) {
				while (chart.firstVisibleIndex > 0) {
					chart.firstVisibleIndex--;
					chart.lastVisibleIndex--;
					newX = getChartX(chart, chart.crossStopIndex);
					if (newX >= oldX) {
						break;
					}
				}
			}
		}
		checkChartLastVisibleIndex(chart);
		if (chart.paint!.onCalculateChartMaxMin) {
			chart.paint!.onCalculateChartMaxMin(chart);
		} else {
			calculateChartMaxMin(chart);
		}
	}
}

/*
* 放大
* chart:图表
*/
function zoomInChart(chart : FCChart) {
	if (!chart.autoFillHScale) {
		let hScalePixel = chart.hScalePixel;
		let oldX = getChartX(chart, chart.crossStopIndex);
		let pureH = getChartWorkAreaWidth(chart);
		let max = -1;
		let dataCount = chart.data.length;
		let findex = chart.firstVisibleIndex, lindex = chart.lastVisibleIndex;
		if (hScalePixel > 3) {
			hScalePixel -= 1;
		} else {
			hScalePixel = hScalePixel * 2 / 3;
			if (hScalePixel > 3) {
				hScalePixel = Math.floor(hScalePixel);
			}
		}
		max = getChartMaxVisibleCount(chart, hScalePixel, pureH);
		if (max >= dataCount) {
			if (hScalePixel < 1) {
				hScalePixel = pureH / max;
			}
			findex = 0;
			lindex = dataCount - 1;
		} else {
			findex = lindex - max + 1;
			if (findex < 0) {
				findex = 0;
			}
		}
		chart.hScalePixel = hScalePixel;
		chart.firstVisibleIndex = findex;
		chart.lastVisibleIndex = lindex;
		if (chart.showCrossLine) {
			let newX = getChartX(chart, chart.crossStopIndex);
			if (newX > oldX) {
				while (chart.lastVisibleIndex < chart.data.length - 1) {
					chart.firstVisibleIndex++;
					chart.lastVisibleIndex++;
					newX = getChartX(chart, chart.crossStopIndex);
					if (newX <= oldX) {
						break;
					}
				}

			}
			else if (newX < oldX) {
				while (chart.firstVisibleIndex > 0) {
					chart.firstVisibleIndex--;
					chart.lastVisibleIndex--;
					newX = getChartX(chart, chart.crossStopIndex);
					if (newX >= oldX) {
						break;
					}
				}
			}
		}
		checkChartLastVisibleIndex(chart);
		if (chart.paint!.onCalculateChartMaxMin) {
			chart.paint!.onCalculateChartMaxMin(chart);
		} else {
			calculateChartMaxMin(chart);
		}
	}
}

/*
* 绘制刻度
* chart:图表
* paint:绘图对象
* clipRect:裁剪区域
*/
function drawChartScale(chart : FCChart, paint : FCPaint, clipRect : FCRect) {
	if (chart.leftVScaleWidth > 0) {
		paint.drawLine(chart.scaleColor, chart.lineWidthChart, null, chart.leftVScaleWidth, 0, chart.leftVScaleWidth, chart.size.cy - chart.hScaleHeight);
	}
	if (chart.rightVScaleWidth > 0) {
		paint.drawLine(chart.scaleColor, chart.lineWidthChart, null, chart.size.cx - chart.rightVScaleWidth, 0, chart.size.cx - chart.rightVScaleWidth, chart.size.cy - chart.hScaleHeight);
	}
	if (chart.hScaleHeight > 0) {
		paint.drawLine(chart.scaleColor, chart.lineWidthChart, null, 0, chart.size.cy - chart.hScaleHeight, chart.size.cx, chart.size.cy - chart.hScaleHeight);
	}
	let candleDivHeight = getCandleDivHeight(chart);
	let volDivHeight = getVolDivHeight(chart);
	let indDivHeight = getIndDivHeight(chart);
	let indDivHeight2 = getIndDivHeight2(chart);
	if (volDivHeight > 0) {
		paint.drawLine(chart.scaleColor, chart.lineWidthChart, null, chart.leftVScaleWidth, candleDivHeight, chart.size.cx - chart.rightVScaleWidth, candleDivHeight);
	}
	if (indDivHeight > 0) {
		paint.drawLine(chart.scaleColor, chart.lineWidthChart, null, chart.leftVScaleWidth, candleDivHeight + volDivHeight, chart.size.cx - chart.rightVScaleWidth, candleDivHeight + volDivHeight);
	}
	if (indDivHeight2 > 0) {
		paint.drawLine(chart.scaleColor, chart.lineWidthChart, null, chart.leftVScaleWidth, candleDivHeight + volDivHeight + indDivHeight, chart.size.cx - chart.rightVScaleWidth, candleDivHeight + volDivHeight + indDivHeight);
	}
	let topPoint = new FCPoint(0, 10);
	let bottomPoint = new FCPoint(0, candleDivHeight - 10);
	let candleMax = getChartValue(chart, topPoint);
	let candleMin = getChartValue(chart, bottomPoint);
	chartGridScale(chart, candleMin, candleMax, (candleDivHeight - chart.candlePaddingTop - chart.candlePaddingBottom) / 2, chart.vScaleDistance, chart.vScaleDistance / 2, Math.floor((candleDivHeight - chart.candlePaddingTop - chart.candlePaddingBottom) / chart.vScaleDistance));
	if (chart.gridStepChart > 0) {
		let drawValues : Array<number> = [];
		let isTrend = chart.cycle == "trend";
		let firstOpen = 0;
		if (isTrend) {
			firstOpen = chart.data[chart.firstVisibleIndex].close;
			let subValue = (candleMax - candleMin);
			let count = (candleDivHeight - chart.candlePaddingTop - chart.candlePaddingBottom) / chart.vScaleDistance;
			if (count > 0) {
				subValue /= count;
			}
			let start = firstOpen;
			while (start < candleMax) {
				start += subValue;
				if (start <= candleMax) {
					drawValues.push(start);
				}
			}
			start = firstOpen;
			while (start > candleMin) {
				start -= subValue;
				if (start >= candleMin) {
					drawValues.push(start);
				}
			}
		} else {
			let start = 0;
			if (candleMin >= 0) {
				while (start + chart.gridStepChart < candleMin) {
					start += chart.gridStepChart;
				}
			} else {
				while (start - chart.gridStepChart > candleMin) {
					start -= chart.gridStepChart;
				}
			}

			while (start <= candleMax) {
				if (start > candleMin) {
					drawValues.push(start);
				}
				start += chart.gridStepChart;
			}
		}
		drawValues.push(firstOpen);
		for (let i = 0; i < drawValues.length; i++) {
			let start = drawValues[i];
			let hAxisY = getChartY(chart, 0, start);
			if (hAxisY < 1 || hAxisY > candleDivHeight) {
				continue;
			}
			paint.drawLine(chart.gridColor, chart.lineWidthChart, [1, 1], chart.leftVScaleWidth, Math.floor(hAxisY), chart.size.cx - chart.rightVScaleWidth, Math.floor(hAxisY));
			paint.drawLine(chart.scaleColor, chart.lineWidthChart, null, chart.leftVScaleWidth - 8, Math.floor(hAxisY), chart.leftVScaleWidth, Math.floor(hAxisY));
			paint.drawLine(chart.scaleColor, chart.lineWidthChart, null, chart.size.cx - chart.rightVScaleWidth, Math.floor(hAxisY), chart.size.cx - chart.rightVScaleWidth + 8, Math.floor(hAxisY));
			let drawText = start.toFixed(chart.candleDigit);
			let tSize = paint.textSize(drawText, chart.font);
			if (isTrend) {
				let diffRange = ((start - firstOpen) / firstOpen * 100);
				let diffRangeStr = diffRange.toFixed(2) + "%";
				if (diffRange >= 0) {
					paint.drawText(diffRangeStr, chart.upColor, chart.font, chart.size.cx - chart.rightVScaleWidth + 10, Math.floor(hAxisY) - tSize.cy / 2);
				} else {
					paint.drawText(diffRangeStr, chart.downColor, chart.font, chart.size.cx - chart.rightVScaleWidth + 10, Math.floor(hAxisY) - tSize.cy / 2);
				}
			} else {
				paint.drawText(drawText, chart.textColor, chart.font, chart.size.cx - chart.rightVScaleWidth + 10, Math.floor(hAxisY) - tSize.cy / 2);
			}
			paint.drawText(drawText, chart.textColor, chart.font, chart.leftVScaleWidth - tSize.cx - 10, Math.floor(hAxisY) - tSize.cy / 2);
		}
	}
	topPoint = new FCPoint(0, candleDivHeight + 10);
	bottomPoint = new FCPoint(0, candleDivHeight + volDivHeight - 10);
	let volMax = getChartValue(chart, topPoint);
	let volMin = getChartValue(chart, bottomPoint);
	chartGridScale(chart, volMin, volMax, (volDivHeight - chart.volPaddingTop - chart.volPaddingBottom) / 2, chart.vScaleDistance, chart.vScaleDistance / 2, Math.floor((volDivHeight - chart.volPaddingTop - chart.volPaddingBottom) / chart.vScaleDistance));
	if (chart.gridStepChart > 0) {
		let start = 0;
		if (volMin >= 0) {
			while (start + chart.gridStepChart < volMin) {
				start += chart.gridStepChart;
			}
		} else {
			while (start - chart.gridStepChart > volMin) {
				start -= chart.gridStepChart;
			}
		}
		while (start <= volMax) {
			if (start > volMin) {
				let hAxisY = getChartY(chart, 1, start);
				if (hAxisY < candleDivHeight || hAxisY > candleDivHeight + volDivHeight) {
					continue;
				}
				paint.drawLine(chart.gridColor, chart.lineWidthChart, [1, 1], chart.leftVScaleWidth, Math.floor(hAxisY), chart.size.cx - chart.rightVScaleWidth, Math.floor(hAxisY));
				paint.drawLine(chart.scaleColor, chart.lineWidthChart, null, chart.leftVScaleWidth - 8, Math.floor(hAxisY), chart.leftVScaleWidth, Math.floor(hAxisY));
				paint.drawLine(chart.scaleColor, chart.lineWidthChart, null, chart.size.cx - chart.rightVScaleWidth, Math.floor(hAxisY), chart.size.cx - chart.rightVScaleWidth + 8, Math.floor(hAxisY));
				let drawText = (start / chart.magnitude).toFixed(chart.volDigit);
				let tSize = paint.textSize(drawText, chart.font);
				paint.drawText(drawText, chart.textColor, chart.font, chart.size.cx - chart.rightVScaleWidth + 10, Math.floor(hAxisY) - tSize.cy / 2);
				paint.drawText(drawText, chart.textColor, chart.font, chart.leftVScaleWidth - tSize.cx - 10, Math.floor(hAxisY) - tSize.cy / 2);
			}
			start += chart.gridStepChart;
		}
	}
	if (indDivHeight > 0) {
		topPoint = new FCPoint(0, candleDivHeight + volDivHeight + 10);
		bottomPoint = new FCPoint(0, candleDivHeight + volDivHeight + indDivHeight - 10);
		let indMax = getChartValue(chart, topPoint);
		let indMin = getChartValue(chart, bottomPoint);
		chartGridScale(chart, indMin, indMax, (indDivHeight - chart.indPaddingTop - chart.indPaddingBottom) / 2, chart.vScaleDistance, chart.vScaleDistance / 2, Math.floor((indDivHeight - chart.indPaddingTop - chart.indPaddingBottom) / chart.vScaleDistance));
		if (chart.gridStepChart > 0) {
			let start = 0;
			if (indMin >= 0) {
				while (start + chart.gridStepChart < indMin) {
					start += chart.gridStepChart;
				}
			} else {
				while (start - chart.gridStepChart > indMin) {
					start -= chart.gridStepChart;
				}
			}

			while (start <= indMax) {
				if (start > indMin) {
					let hAxisY = getChartY(chart, 2, start);
					if (hAxisY < candleDivHeight + volDivHeight || hAxisY > candleDivHeight + volDivHeight + indDivHeight) {
						continue;
					}
					paint.drawLine(chart.gridColor, chart.lineWidthChart, [1, 1], chart.leftVScaleWidth, Math.floor(hAxisY), chart.size.cx - chart.rightVScaleWidth, Math.floor(hAxisY));
					paint.drawLine(chart.scaleColor, chart.lineWidthChart, null, chart.leftVScaleWidth - 8, Math.floor(hAxisY), chart.leftVScaleWidth, Math.floor(hAxisY));
					paint.drawLine(chart.scaleColor, chart.lineWidthChart, null, chart.size.cx - chart.rightVScaleWidth, Math.floor(hAxisY), chart.size.cx - chart.rightVScaleWidth + 8, Math.floor(hAxisY));
					let drawText = start.toFixed(chart.indDigit);
					let tSize = paint.textSize(drawText, chart.font);
					paint.drawText(drawText, chart.textColor, chart.font, chart.size.cx - chart.rightVScaleWidth + 10, Math.floor(hAxisY) - tSize.cy / 2);
					paint.drawText(drawText, chart.textColor, chart.font, chart.leftVScaleWidth - tSize.cx - 10, Math.floor(hAxisY) - tSize.cy / 2);
				}
				start += chart.gridStepChart;
			}
		}
	}
	if (indDivHeight2 > 0) {
		topPoint = new FCPoint(0, candleDivHeight + volDivHeight + indDivHeight + 10);
		bottomPoint = new FCPoint(0, candleDivHeight + volDivHeight + indDivHeight + indDivHeight2 - 10);
		let indMax2 = getChartValue(chart, topPoint);
		let indMin2 = getChartValue(chart, bottomPoint);
		chartGridScale(chart, indMin2, indMax2, (indDivHeight2 - chart.indPaddingTop2 - chart.indPaddingBottom2) / 2, chart.vScaleDistance, chart.vScaleDistance / 2, Math.floor((indDivHeight2 - chart.indPaddingTop2 - chart.indPaddingBottom2) / chart.vScaleDistance));
		if (chart.gridStepChart > 0) {
			let start = 0;
			if (indMin2 >= 0) {
				while (start + chart.gridStepChart < indMin2) {
					start += chart.gridStepChart;
				}
			} else {
				while (start - chart.gridStepChart > indMin2) {
					start -= chart.gridStepChart;
				}
			}

			while (start <= indMax2) {
				if (start > indMin2) {
					let hAxisY = getChartY(chart, 3, start);
					if (hAxisY < candleDivHeight + volDivHeight + indDivHeight || hAxisY > candleDivHeight + volDivHeight + indDivHeight + indDivHeight2) {
						continue;
					}
					paint.drawLine(chart.gridColor, chart.lineWidthChart, [1, 1], chart.leftVScaleWidth, Math.floor(hAxisY), chart.size.cx - chart.rightVScaleWidth, Math.floor(hAxisY));
					paint.drawLine(chart.scaleColor, chart.lineWidthChart, null, chart.leftVScaleWidth - 8, Math.floor(hAxisY), chart.leftVScaleWidth, Math.floor(hAxisY));
					paint.drawLine(chart.scaleColor, chart.lineWidthChart, null, chart.size.cx - chart.rightVScaleWidth, Math.floor(hAxisY), chart.size.cx - chart.rightVScaleWidth + 8, Math.floor(hAxisY));
					let drawText = start.toFixed(chart.indDigit);
					let tSize = paint.textSize(drawText, chart.font);
					paint.drawText(drawText, chart.textColor, chart.font, chart.size.cx - chart.rightVScaleWidth + 10, Math.floor(hAxisY) - tSize.cy / 2);
					paint.drawText(drawText, chart.textColor, chart.font, chart.leftVScaleWidth - tSize.cx - 10, Math.floor(hAxisY) - tSize.cy / 2);
				}
				start += chart.gridStepChart;
			}
		}
	}
	if (paint.onPaintChartHScale != null) {
		paint.onPaintChartHScale!(chart, paint, clipRect);
	} else {
		if (chart.data != null && chart.data.length > 0 && chart.hScaleHeight > 0) {
			let dLeft = chart.leftVScaleWidth + 10;
			for (let i = chart.firstVisibleIndex; i <= chart.lastVisibleIndex; i++) {
				let date = new Date();
				date.setTime(chart.data[i].date);
				let xText = "";
				if (chart.hScaleFormat.length > 0) {
					xText = dateFormat(chart.hScaleFormat, date);
				} else {
					if (chart.cycle == "day") {
						xText = dateFormat("YYYY-mm-dd", date);
					} else if (chart.cycle == "minute") {
						xText = dateFormat("YYYY-mm-dd HH:MM", date);
					} else if (chart.cycle == "trend") {
						xText = dateFormat("HH:MM", date);
					}
					else if (chart.cycle == "second") {
						xText = dateFormat("HH:MM:SS", date);
					}
					else if (chart.cycle == "tick") {
						xText = (i + 1).toString();
					}
				}
				let tSize = paint.textSize(xText, chart.font);
				let x = getChartX(chart, i);
				let dx = x - tSize.cx / 2;
				if (dx > dLeft && dx < chart.size.cx - chart.rightVScaleWidth - 10) {
					paint.drawLine(chart.scaleColor, chart.lineWidthChart, null, x, chart.size.cy - chart.hScaleHeight, x, chart.size.cy - chart.hScaleHeight + 8);
					paint.drawText(xText, chart.textColor, chart.font, dx, chart.size.cy - chart.hScaleHeight + 8 - tSize.cy / 2 + 7);
					i = i + Math.floor((tSize.cx + chart.hScaleTextDistance) / chart.hScalePixel) + 1
				}
			}
		}
	}
}

/*
* 绘制十字线
* chart:图表
* paint:绘图对象
* clipRect:裁剪区域
*/
function drawChartCrossLine(chart : FCChart, paint : FCPaint, clipRect : FCRect) {
	if (chart.data == null || chart.data.length == 0) {
		return;
	}
	let candleDivHeight = getCandleDivHeight(chart);
	let volDivHeight = getVolDivHeight(chart);
	let indDivHeight = getIndDivHeight(chart);
	let indDivHeight2 = getIndDivHeight2(chart);
	let crossLineIndex = chart.crossStopIndex;
	if (crossLineIndex == -1 || !chart.showCrossLine) {
		crossLineIndex = chart.lastVisibleIndex;
	}
	let str = "A" + crossLineIndex;
	if (str == "ANaN") {
		crossLineIndex = chart.lastVisibleIndex;
	}
	if (volDivHeight > 0) {
		let drawTitles : Array<string> = [];
		let drawColors : Array<string> = [];
		drawTitles.push("VOL " + chart.data[crossLineIndex].volume.toFixed(chart.volDigit));
		drawColors.push(chart.textColor);
		if (chart.shapes.length > 0) {
			for (let i = 0; i < chart.shapes.length; i++) {
				let shape = chart.shapes[i]
				if (shape.divIndex == 1) {
					if (shape.title.length > 0) {
						if (shape.shapeType == "bar" && shape.style == "2color") {
							drawTitles.push(shape.title + " " + shape.datas[crossLineIndex].toFixed(chart.volDigit));
							drawColors.push(shape.color2!);
						} else {
							if (shape.shapeType != "text") {
								drawTitles.push(shape.title + " " + shape.datas[crossLineIndex].toFixed(chart.volDigit));
								drawColors.push(shape.color!);
								if (shape.datas2.length > 0) {
									drawTitles.push(shape.title2 + " " + shape.datas2[crossLineIndex].toFixed(chart.volDigit));
									drawColors.push(shape.color2!);
								}
							}
						}
					}
				}
			}
		}
		let iLeft = chart.leftVScaleWidth + 5;
		for (let i = 0; i < drawTitles.length; i++) {
			let tSize = paint.textSize(drawTitles[i], chart.font);
			paint.drawText(drawTitles[i], drawColors[i], chart.font, iLeft, candleDivHeight + 5);
			iLeft += tSize.cx + 5;
		}
	}
	//上面显示数据  高开低收
	if (chart.cycle == "trend") {
		let drawTitles : Array<string> = [];
		let drawColors : Array<string> = [];
		drawTitles.push("CLOSE " + chart.data[crossLineIndex].close.toFixed(chart.candleDigit));
		drawColors.push(chart.textColor);
		if (chart.shapes.length > 0) {
			for (let i = 0; i < chart.shapes.length; i++) {
				let shape = chart.shapes[i];
				if (shape.divIndex == 0) {
					if (shape.title.length > 0) {
						if (shape.shapeType == "bar" && shape.style == "2color") {
							drawTitles.push(shape.title + " " + shape.datas[crossLineIndex].toFixed(chart.candleDigit));
							drawColors.push(shape.color2!);
						} else {
							if (shape.shapeType != "text") {
								drawTitles.push(shape.title + " " + shape.datas[crossLineIndex].toFixed(chart.candleDigit));
								drawColors.push(shape.color!);
								if (shape.datas2.length > 0) {
									drawTitles.push(shape.title2 + " " + shape.datas2[crossLineIndex].toFixed(chart.candleDigit));
									drawColors.push(shape.color2!);
								}
							}
						}
					}
				}
			}
		}
		let iLeft = chart.leftVScaleWidth + 5;
		for (let i = 0; i < drawTitles.length; i++) {
			let tSize = paint.textSize(drawTitles[i], chart.font);
			paint.drawText(drawTitles[i], drawColors[i], chart.font, iLeft, 5);
			iLeft += tSize.cx + 5;
		}
	} else {
		let drawTitles : Array<string> = [];
		let drawColors : Array<string> = [];
		if (chart.mainIndicator == "MA") {
			if (chart.ma5 != null && chart.ma5.length > 0) {
				drawTitles.push("MA5 " + chart.ma5[crossLineIndex].toFixed(chart.candleDigit));
			} else {
				drawTitles.push("MA5")
			}
			drawColors.push(chart.indicatorColors[0]);
			if (chart.ma10 != null && chart.ma10.length > 0) {
				drawTitles.push("MA10 " + chart.ma10[crossLineIndex].toFixed(chart.candleDigit));
			} else {
				drawTitles.push("MA10");
			}
			drawColors.push(chart.indicatorColors[1]);
			if (chart.ma20 != null && chart.ma20.length > 0) {
				drawTitles.push("MA20 " + chart.ma20[crossLineIndex].toFixed(chart.candleDigit));

			} else {
				drawTitles.push("MA20");
			}
			drawColors.push(chart.indicatorColors[2]);
			if (chart.ma30 != null && chart.ma30.length > 0) {
				drawTitles.push("MA30 " + chart.ma30[crossLineIndex].toFixed(chart.candleDigit));
			} else {
				drawTitles.push("MA30");
			}
			drawColors.push(chart.indicatorColors[5]);
			if (chart.ma120 != null && chart.ma120.length > 0) {
				drawTitles.push("MA120 " + chart.ma120[crossLineIndex].toFixed(chart.candleDigit));

			} else {
				drawTitles.push("MA120");
			}
			drawColors.push(chart.indicatorColors[4]);
			if (chart.ma250 != null && chart.ma250.length > 0) {
				drawTitles.push("MA250 " + chart.ma250[crossLineIndex].toFixed(chart.candleDigit));
			} else {
				drawTitles.push("MA250");
			}
			drawColors.push(chart.indicatorColors[3]);
		} else if (chart.mainIndicator == "BOLL") {
			if (chart.bollMid != null && chart.bollMid.length > 0) {
				drawTitles.push("MID " + chart.bollMid[crossLineIndex].toFixed(chart.candleDigit));
			} else {
				drawTitles.push("MID");
			}
			drawColors.push(chart.indicatorColors[0]);
			if (chart.bollUp != null && chart.bollUp.length > 0) {
				drawTitles.push("UP " + chart.bollUp[crossLineIndex].toFixed(chart.candleDigit));
			} else {
				drawTitles.push("UP");
			}
			drawColors.push(chart.indicatorColors[1]);
			if (chart.bollDown != null && chart.bollDown.length > 0) {
				drawTitles.push("LOW " + chart.bollDown[crossLineIndex].toFixed(chart.candleDigit));
			} else {
				drawTitles.push("LOW");
			}
			drawColors.push(chart.indicatorColors[2]);
		}
		if (chart.shapes.length > 0) {
			for (let i = 0; i < chart.shapes.length; i++) {
				let shape = chart.shapes[i];
				if (shape.divIndex == 0) {
					if (shape.title.length > 0) {
						if (shape.shapeType == "bar" && shape.style == "2color") {
							drawTitles.push(shape.title + " " + shape.datas[crossLineIndex].toFixed(chart.candleDigit));
							drawColors.push(shape.color2!);
						} else {
							if (shape.shapeType != "text") {
								drawTitles.push(shape.title + " " + shape.datas[crossLineIndex].toFixed(chart.candleDigit));
								drawColors.push(shape.color!);
								if (shape.datas2.length > 0) {
									drawTitles.push(shape.title2 + " " + shape.datas2[crossLineIndex].toFixed(chart.candleDigit));
									drawColors.push(shape.color2!);
								}
							}
						}
					}
				}
			}
		}
		let iLeft = chart.leftVScaleWidth + 5;
		for (let i = 0; i < drawTitles.length; i++) {
			let tSize = paint.textSize(drawTitles[i], chart.font);
			paint.drawText(drawTitles[i], drawColors[i], chart.font, iLeft, 5);
			iLeft += tSize.cx + 5;
		}
	}
	if (indDivHeight > 0) {
		let drawTitles : Array<string> = [];
		let drawColors : Array<string> = [];
		if (chart.showIndicator == "MACD") {
			if (chart.alldifarr != null && chart.alldifarr.length > 0) {
				drawTitles.push("DIF " + chart.alldifarr[crossLineIndex].toFixed(chart.indDigit));
			} else {
				drawTitles.push("DIF");
			}
			drawColors.push(chart.indicatorColors[0]);
			if (chart.alldeaarr != null && chart.alldeaarr.length > 0) {
				drawTitles.push("DEA " + chart.alldeaarr[crossLineIndex].toFixed(chart.indDigit));
			} else {
				drawTitles.push("DEA");
			}
			drawColors.push(chart.indicatorColors[1]);
			if (chart.allmacdarr != null && chart.allmacdarr.length > 0) {
				drawTitles.push("MACD " + chart.allmacdarr[crossLineIndex].toFixed(chart.indDigit));
			} else {
				drawTitles.push("MACD");
			}
			drawColors.push(chart.indicatorColors[4]);
		} else if (chart.showIndicator == "KDJ") {
			if (chart.kdjK != null && chart.kdjK.length > 0) {
				drawTitles.push("K " + chart.kdjK[crossLineIndex].toFixed(chart.indDigit));
			} else {
				drawTitles.push("K");
			}
			drawColors.push(chart.indicatorColors[0]);
			if (chart.kdjD != null && chart.kdjD.length > 0) {
				drawTitles.push("D " + chart.kdjD[crossLineIndex].toFixed(chart.indDigit));
			} else {
				drawTitles.push("D");
			}
			drawColors.push(chart.indicatorColors[1]);
			if (chart.kdjJ != null && chart.kdjJ.length > 0) {
				drawTitles.push("J " + chart.kdjJ[crossLineIndex].toFixed(chart.indDigit));
			} else {
				drawTitles.push("J");
			}
			drawColors.push(chart.indicatorColors[2]);
		} else if (chart.showIndicator == "RSI") {
			if (chart.rsi1 != null && chart.rsi1.length > 0) {
				drawTitles.push("RSI6 " + chart.rsi1[crossLineIndex].toFixed(chart.indDigit));
			} else {
				drawTitles.push("RSI6");
			}
			drawColors.push(chart.indicatorColors[5]);
			if (chart.rsi2 != null && chart.rsi2.length > 0) {
				drawTitles.push("RSI12 " + chart.rsi2[crossLineIndex].toFixed(chart.indDigit));
			} else {
				drawTitles.push("RSI12");
			}
			drawColors.push(chart.indicatorColors[1]);
			if (chart.rsi3 != null && chart.rsi3.length > 0) {
				drawTitles.push("RSI24 " + chart.rsi3[crossLineIndex].toFixed(chart.indDigit));
			} else {
				drawTitles.push("RSI24");
			}
			drawColors.push(chart.indicatorColors[2]);
		}
		else if (chart.showIndicator == "BIAS") {
			if (chart.bias1 != null && chart.bias1.length > 0) {
				drawTitles.push("BIAS6 " + chart.bias1[crossLineIndex].toFixed(chart.indDigit));
			} else {
				drawTitles.push("BIAS6");
			}
			drawColors.push(chart.indicatorColors[5]);
			if (chart.bias2 != null && chart.bias2.length > 0) {
				drawTitles.push("BIAS12 " + chart.bias2[crossLineIndex].toFixed(chart.indDigit));
			} else {
				drawTitles.push("BIAS12");
			}
			drawColors.push(chart.indicatorColors[1]);
			if (chart.bias3 != null && chart.bias3.length > 0) {
				drawTitles.push("BIAS24 " + chart.bias3[crossLineIndex].toFixed(chart.indDigit));
			} else {
				drawTitles.push("BIAS24");
			}
			drawColors.push(chart.indicatorColors[2]);
		}
		else if (chart.showIndicator == "ROC") {
			if (chart.roc != null && chart.roc.length > 0) {
				drawTitles.push("ROC " + chart.roc[crossLineIndex].toFixed(chart.indDigit));
			} else {
				drawTitles.push("ROC");
			}
			drawColors.push(chart.indicatorColors[0]);
			if (chart.rocMa != null && chart.rocMa.length > 0) {
				drawTitles.push("ROCMA " + chart.rocMa[crossLineIndex].toFixed(chart.indDigit));
			} else {
				drawTitles.push("ROCMA");
			}
			drawColors.push(chart.indicatorColors[1]);
		}
		else if (chart.showIndicator == "WR") {
			if (chart.wr1 != null && chart.wr1.length > 0) {
				drawTitles.push("WR5 " + chart.wr1[crossLineIndex].toFixed(chart.indDigit));
			} else {
				drawTitles.push("WR5");
			}
			drawColors.push(chart.indicatorColors[0]);
			if (chart.wr2 != null && chart.wr2.length > 0) {
				drawTitles.push("WR10 " + chart.wr2[crossLineIndex].toFixed(chart.indDigit));
			} else {
				drawTitles.push("WR10");
			}
			drawColors.push(chart.indicatorColors[1]);
		}
		else if (chart.showIndicator == "CCI") {
			if (chart.cci != null && chart.cci.length > 0) {
				drawTitles.push("CCI " + chart.cci[crossLineIndex].toFixed(chart.indDigit));
			} else {
				drawTitles.push("CCI");
			}
			drawColors.push(chart.indicatorColors[0]);
		} else if (chart.showIndicator == "BBI") {
			if (chart.bbi != null && chart.bbi.length > 0) {
				drawTitles.push("BBI " + chart.bbi[crossLineIndex].toFixed(chart.indDigit));
			} else {
				drawTitles.push("BBI");
			}
			drawColors.push(chart.indicatorColors[0]);
		} else if (chart.showIndicator == "TRIX") {
			if (chart.trix != null && chart.trix.length > 0) {
				drawTitles.push("TRIX " + chart.trix[crossLineIndex].toFixed(chart.indDigit));
			} else {
				drawTitles.push("TRIX");
			}
			drawColors.push(chart.indicatorColors[0]);
			if (chart.trixMa != null && chart.trixMa.length > 0) {
				drawTitles.push("TRIXMA " + chart.trixMa[crossLineIndex].toFixed(chart.indDigit));
			} else {
				drawTitles.push("TRIXMA");
			}
			drawColors.push(chart.indicatorColors[1]);
		}
		else if (chart.showIndicator == "DMA") {
			if (chart.dma1 != null && chart.dma1.length > 0) {
				drawTitles.push("MA10 " + chart.dma1[crossLineIndex].toFixed(chart.indDigit));
			} else {
				drawTitles.push("MA10");
			}
			drawColors.push(chart.indicatorColors[0]);
			if (chart.dma2 != null && chart.dma2.length > 0) {
				drawTitles.push("MA50 " + chart.dma2[crossLineIndex].toFixed(chart.indDigit));
			} else {
				drawTitles.push("MA50");
			}
			drawColors.push(chart.indicatorColors[1]);
		}
		if (chart.shapes.length > 0) {
			for (let i = 0; i < chart.shapes.length; i++) {
				let shape = chart.shapes[i];
				if (shape.divIndex == 2) {
					if (shape.title.length > 0) {
						if (shape.shapeType == "bar" && shape.style == "2color") {
							drawTitles.push(shape.title + " " + shape.datas[crossLineIndex].toFixed(chart.indDigit));
							drawColors.push(shape.color2!);
						} else {
							if (shape.shapeType != "text") {
								drawTitles.push(shape.title + " " + shape.datas[crossLineIndex].toFixed(chart.indDigit));
								drawColors.push(shape.color!);
								if (shape.datas2.length > 0) {
									drawTitles.push(shape.title2 + " " + shape.datas2[crossLineIndex].toFixed(chart.indDigit));
									drawColors.push(shape.color2!);
								}
							}
						}
					}
				}
			}
		}
		let iLeft = chart.leftVScaleWidth + 5;
		for (let i = 0; i < drawTitles.length; i++) {
			let tSize = paint.textSize(drawTitles[i], chart.font);
			paint.drawText(drawTitles[i], drawColors[i], chart.font, iLeft, candleDivHeight + volDivHeight + 5);
			iLeft += tSize.cx + 5;
		}
	}
	if (indDivHeight2 > 0) {
		let drawTitles : Array<string> = [];
		let drawColors : Array<string> = [];
		if (chart.shapes.length > 0) {
			for (let i = 0; i < chart.shapes.length; i++) {
				let shape = chart.shapes[i];
				if (shape.divIndex == 3) {
					if (shape.title.length > 0) {
						if (shape.shapeType == "bar" && shape.style == "2color") {
							drawTitles.push(shape.title + " " + shape.datas[crossLineIndex].toFixed(chart.indDigit2));
							drawColors.push(shape.color2!);
						} else {
							if (shape.shapeType != "text") {
								drawTitles.push(shape.title + " " + shape.datas[crossLineIndex].toFixed(chart.indDigit2));
								drawColors.push(shape.color!);
								if (shape.datas2.length > 0) {
									drawTitles.push(shape.title2 + " " + shape.datas2[crossLineIndex].toFixed(chart.indDigit2));
									drawColors.push(shape.color2!);
								}
							}
						}
					}
				}
			}
		}
		if (drawTitles.length > 0) {
			let iLeft = chart.leftVScaleWidth + 5;
			for (let i = 0; i < drawTitles.length; i++) {
				let tSize = paint.textSize(drawTitles[i], chart.font);
				paint.drawText(drawTitles[i], drawColors[i], chart.font, iLeft, candleDivHeight + volDivHeight + indDivHeight + 5);
				iLeft += tSize.cx + 5;
			}
		}
	}

	if (chart.showCrossLine) {
		let rightText = "";
		if (chart.touchPosition.y < candleDivHeight) {
			rightText = getChartValue(chart, chart.touchPosition).toFixed(chart.candleDigit);
		}
		else if (chart.touchPosition.y > candleDivHeight && chart.touchPosition.y < candleDivHeight + volDivHeight) {
			rightText = getChartValue(chart, chart.touchPosition).toFixed(chart.volDigit);
		} else if (chart.touchPosition.y > candleDivHeight + volDivHeight && chart.touchPosition.y < candleDivHeight + volDivHeight + indDivHeight) {
			rightText = getChartValue(chart, chart.touchPosition).toFixed(chart.indDigit);
		} else if (chart.touchPosition.y > candleDivHeight + volDivHeight + indDivHeight && chart.touchPosition.y < candleDivHeight + volDivHeight + indDivHeight + indDivHeight2) {
			rightText = getChartValue(chart, chart.touchPosition).toFixed(chart.indDigit2);
		}

		let drawY = chart.touchPosition.y;
		if (drawY > chart.size.cy - chart.hScaleHeight) {
			drawY = chart.size.cy - chart.hScaleHeight;
		}
		let tSize = paint.textSize(rightText, chart.font);
		if (chart.leftVScaleWidth > 0) {
			paint.fillRect(chart.crossTipColor, chart.leftVScaleWidth - tSize.cx, drawY - tSize.cy / 2 - 4, chart.leftVScaleWidth, drawY + tSize.cy / 2 + 3);
			paint.drawText(rightText, chart.textColor, chart.font, chart.leftVScaleWidth - tSize.cx, drawY - tSize.cy / 2);
		}
		if (chart.rightVScaleWidth > 0) {
			paint.fillRect(chart.crossTipColor, chart.size.cx - chart.rightVScaleWidth, drawY - tSize.cy / 2 - 4, chart.size.cx - chart.rightVScaleWidth + tSize.cx, drawY + tSize.cy / 2 + 3);
			paint.drawText(rightText, chart.textColor, chart.font, chart.size.cx - chart.rightVScaleWidth, drawY - tSize.cy / 2);
		}
		//绘制十字线
		let drawX = chart.touchPosition.x;
		if (drawX < chart.leftVScaleWidth) {
			drawX = chart.leftVScaleWidth;
		}
		if (drawX > chart.size.cx - chart.rightVScaleWidth) {
			drawX = chart.size.cx - chart.rightVScaleWidth;
		}
		if (chart.sPlot == null && chart.selectShape == "") {
			paint.drawLine(chart.crossLineColor, chart.lineWidthChart, null, chart.leftVScaleWidth, drawY, chart.size.cx - chart.rightVScaleWidth, drawY);
			paint.drawLine(chart.crossLineColor, chart.lineWidthChart, null, drawX, 0, drawX, chart.size.cy - chart.hScaleHeight);
		}
		let str = "A" + chart.crossStopIndex;
		if (chart.crossStopIndex != -1 && str != "ANaN") {
			let date = new Date();
			date.setTime(chart.data[chart.crossStopIndex].date);
			let xText = "";
			if (chart.cycle == "day") {
				xText = dateFormat("YYYY-mm-dd", date);
			} else if (chart.cycle == "minute") {
				xText = dateFormat("YYYY-mm-dd HH:MM", date);
			} else if (chart.cycle == "trend") {
				xText = dateFormat("HH:MM", date);
			}
			else if (chart.cycle == "second") {
				xText = dateFormat("HH:MM:SS", date);
			}
			else if (chart.cycle == "tick") {
				xText = (chart.crossStopIndex + 1).toString();
			}
			if (chart.hScaleFormat.length > 0) {
				xText = dateFormat(chart.hScaleFormat, date);
			}
			let xSize = paint.textSize(xText, chart.font);
			paint.fillRect(chart.crossTipColor, drawX - xSize.cx / 2 - 2, candleDivHeight + volDivHeight + indDivHeight, drawX + xSize.cx / 2 + 2, candleDivHeight + volDivHeight + indDivHeight + xSize.cy + 6);
			paint.drawText(xText, chart.textColor, chart.font, drawX - xSize.cx / 2, candleDivHeight + volDivHeight + indDivHeight + 3);
		}
	}
}

/*
* 计算最大最小值
* chart:图表
*/
function calculateChartMaxMin(chart : FCChart) {
	chart.candleMax = 0;
	chart.candleMin = 0;
	chart.volMax = 0;
	chart.volMin = 0;
	chart.indMin = 0;
	chart.indMin = 0;
	var load1 = false;
	var load2 = false;
	var load3 = false;
	var load4 = false;
	let isTrend = chart.cycle == "trend";
	var firstOpen = 0.0;
	if (chart.data.length > 0) {
		var lastValidIndex = chart.lastVisibleIndex;
		if (chart.lastValidIndex != -1) {
			lastValidIndex = chart.lastValidIndex;
		}
		for (let i = chart.firstVisibleIndex; i <= lastValidIndex; i++) {
			if (i == chart.firstVisibleIndex) {
				if (isTrend) {
					chart.candleMax = chart.data[i].close;
					chart.candleMin = chart.data[i].close;
					firstOpen = chart.data[i].close;
				} else {
					chart.candleMax = chart.data[i].high;
					chart.candleMin = chart.data[i].low;
				}
				chart.volMax = chart.data[i].volume;
				load1 = true;
				load2 = true;
				if (chart.showIndicator == "MACD") {
					chart.indMax = chart.alldifarr[i];
					chart.indMin = chart.alldifarr[i];
					load3 = true;
				}
				else if (chart.showIndicator == "KDJ") {
					chart.indMax = chart.kdjK[i];
					chart.indMin = chart.kdjK[i];
					load3 = true;
				}
				else if (chart.showIndicator == "RSI") {
					chart.indMax = chart.rsi1[i];
					chart.indMin = chart.rsi1[i];
					load3 = true;
				}
				else if (chart.showIndicator == "BIAS") {
					chart.indMax = chart.bias1[i];
					chart.indMin = chart.bias1[i];
					load3 = true;
				}
				else if (chart.showIndicator == "ROC") {
					chart.indMax = chart.roc[i];
					chart.indMin = chart.roc[i];
					load3 = true;
				}
				else if (chart.showIndicator == "WR") {
					chart.indMax = chart.wr1[i];
					chart.indMin = chart.wr1[i];
					load3 = true;
				} else if (chart.showIndicator == "CCI") {
					chart.indMax = chart.cci[i];
					chart.indMin = chart.cci[i];
					load3 = true;
				} else if (chart.showIndicator == "BBI") {
					chart.indMax = chart.bbi[i];
					chart.indMin = chart.bbi[i];
					load3 = true;
				}
				else if (chart.showIndicator == "TRIX") {
					chart.indMax = chart.trix[i];
					chart.indMin = chart.trix[i];
					load3 = true;
				}
				else if (chart.showIndicator == "DMA") {
					chart.indMax = chart.dma1[i];
					chart.indMin = chart.dma1[i];
					load3 = true;
				}
			} else {
				if (isTrend) {
					if (chart.candleMax < chart.data[i].close) {
						chart.candleMax = chart.data[i].close;
					}
					if (chart.candleMin > chart.data[i].close) {
						chart.candleMin = chart.data[i].close;
					}
				} else {
					if (chart.candleMax < chart.data[i].high) {
						chart.candleMax = chart.data[i].high;
					}
					if (chart.candleMin > chart.data[i].low) {
						chart.candleMin = chart.data[i].low;
					}
				}
				if (chart.volMax < chart.data[i].volume) {
					chart.volMax = chart.data[i].volume;
				}
			}
			if (chart.showIndicator == "MACD") {
				if (chart.indMax < chart.alldifarr[i]) {
					chart.indMax = chart.alldifarr[i];
				}
				if (chart.indMax < chart.alldeaarr[i]) {
					chart.indMax = chart.alldeaarr[i];
				}
				if (chart.indMax < chart.allmacdarr[i]) {
					chart.indMax = chart.allmacdarr[i];
				}
				if (chart.indMin > chart.alldifarr[i]) {
					chart.indMin = chart.alldifarr[i];
				}
				if (chart.indMin > chart.alldeaarr[i]) {
					chart.indMin = chart.alldeaarr[i];
				}
				if (chart.indMin > chart.allmacdarr[i]) {
					chart.indMin = chart.allmacdarr[i];
				}
			} else if (chart.showIndicator == "KDJ") {
				if (chart.indMax < chart.kdjK[i]) {
					chart.indMax = chart.kdjK[i];
				}
				if (chart.indMax < chart.kdjD[i]) {
					chart.indMax = chart.kdjD[i];
				}
				if (chart.indMax < chart.kdjJ[i]) {
					chart.indMax = chart.kdjJ[i];
				}
				if (chart.indMin > chart.kdjK[i]) {
					chart.indMin = chart.kdjK[i];
				}
				if (chart.indMin > chart.kdjD[i]) {
					chart.indMin = chart.kdjD[i];
				}
				if (chart.indMin > chart.kdjJ[i]) {
					chart.indMin = chart.kdjJ[i];
				}
			} else if (chart.showIndicator == "RSI") {
				if (chart.indMax < chart.rsi1[i]) {
					chart.indMax = chart.rsi1[i];
				}
				if (chart.indMax < chart.rsi2[i]) {
					chart.indMax = chart.rsi2[i];
				}
				if (chart.indMax < chart.rsi3[i]) {
					chart.indMax = chart.rsi3[i];
				}
				if (chart.indMin > chart.rsi1[i]) {
					chart.indMin = chart.rsi1[i];
				}
				if (chart.indMin > chart.rsi2[i]) {
					chart.indMin = chart.rsi2[i];
				}
				if (chart.indMin > chart.rsi3[i]) {
					chart.indMin = chart.rsi3[i];
				}
			} else if (chart.showIndicator == "BIAS") {
				if (chart.indMax < chart.bias1[i]) {
					chart.indMax = chart.bias1[i];
				}
				if (chart.indMax < chart.bias2[i]) {
					chart.indMax = chart.bias2[i];
				}
				if (chart.indMax < chart.bias3[i]) {
					chart.indMax = chart.bias3[i];
				}
				if (chart.indMin > chart.bias1[i]) {
					chart.indMin = chart.bias1[i];
				}
				if (chart.indMin > chart.bias2[i]) {
					chart.indMin = chart.bias2[i];
				}
				if (chart.indMin > chart.bias3[i]) {
					chart.indMin = chart.bias3[i];
				}
			} else if (chart.showIndicator == "ROC") {
				if (chart.indMax < chart.roc[i]) {
					chart.indMax = chart.roc[i];
				}
				if (chart.indMax < chart.rocMa[i]) {
					chart.indMax = chart.rocMa[i];
				}
				if (chart.indMin > chart.roc[i]) {
					chart.indMin = chart.roc[i];
				}
				if (chart.indMin > chart.rocMa[i]) {
					chart.indMin = chart.rocMa[i];
				}
			}
			else if (chart.showIndicator == "WR") {
				if (chart.indMax < chart.wr1[i]) {
					chart.indMax = chart.wr1[i];
				}
				if (chart.indMax < chart.wr2[i]) {
					chart.indMax = chart.wr2[i];
				}
				if (chart.indMin > chart.wr1[i]) {
					chart.indMin = chart.wr1[i];
				}
				if (chart.indMin > chart.wr2[i]) {
					chart.indMin = chart.wr2[i];
				}
			} else if (chart.showIndicator == "CCI") {
				if (chart.indMax < chart.cci[i]) {
					chart.indMax = chart.cci[i];
				}
				if (chart.indMin > chart.cci[i]) {
					chart.indMin = chart.cci[i];
				}
			} else if (chart.showIndicator == "BBI") {
				if (chart.indMax < chart.bbi[i]) {
					chart.indMax = chart.bbi[i];
				}
				if (chart.indMin > chart.bbi[i]) {
					chart.indMin = chart.bbi[i];
				}
			} else if (chart.showIndicator == "TRIX") {
				if (chart.indMax < chart.trix[i]) {
					chart.indMax = chart.trix[i];
				}
				if (chart.indMax < chart.trixMa[i]) {
					chart.indMax = chart.trixMa[i];
				}
				if (chart.indMin > chart.trix[i]) {
					chart.indMin = chart.trix[i];
				}
				if (chart.indMin > chart.trixMa[i]) {
					chart.indMin = chart.trixMa[i]
				}
			} else if (chart.showIndicator == "DMA") {
				if (chart.indMax < chart.dma1[i]) {
					chart.indMax = chart.dma1[i];
				}
				if (chart.indMax < chart.dma2[i]) {
					chart.indMax = chart.dma2[i];
				}
				if (chart.indMin > chart.dma1[i]) {
					chart.indMin = chart.dma1[i];
				}
				if (chart.indMin > chart.dma2[i]) {
					chart.indMin = chart.dma2[i];
				}
			}
		}
	}
	if (chart.shapes.length > 0) {
		var lastValidIndex = chart.lastVisibleIndex;
		if (chart.lastValidIndex != -1) {
			lastValidIndex = chart.lastValidIndex;
		}
		for (let s = 0; s < chart.shapes.length; s++) {
			let shape = chart.shapes[s];
			if (shape.datas.length > 0) {
				for (let i = chart.firstVisibleIndex; i <= lastValidIndex; i++) {
					if (shape.divIndex == 0) {
						if (!load1 && i == chart.firstVisibleIndex) {
							if (shape.leftOrRight) {
								chart.candleMax = shape.datas[i];
								chart.candleMin = shape.datas[i];
							} else {
								chart.candleMaxRight = shape.datas[i];
								chart.candleMinRight = shape.datas[i];
							}
							load1 = true;
						} else {
							if (shape.leftOrRight) {
								if (shape.datas[i] > chart.candleMax) {
									chart.candleMax = shape.datas[i];
								}
								if (shape.datas[i] < chart.candleMin) {
									chart.candleMin = shape.datas[i];
								}
							} else {
								if (shape.datas[i] > chart.candleMaxRight) {
									chart.candleMaxRight = shape.datas[i];
								}
								if (shape.datas[i] < chart.candleMinRight) {
									chart.candleMinRight = shape.datas[i];
								}
							}
						}
					} else if (shape.divIndex == 1) {
						if (!load2 && i == chart.firstVisibleIndex) {
							if (shape.leftOrRight) {
								chart.volMax = shape.datas[i];
								chart.volMin = shape.datas[i];
							} else {
								chart.volMaxRight = shape.datas[i];
								chart.volMinRight = shape.datas[i];
							}
							load2 = true;
						} else {
							if (shape.leftOrRight) {
								if (shape.datas[i] > chart.volMax) {
									chart.volMax = shape.datas[i];
								}
								if (shape.datas[i] < chart.volMin) {
									chart.volMin = shape.datas[i];
								}
							} else {
								if (shape.datas[i] > chart.volMaxRight) {
									chart.volMaxRight = shape.datas[i];
								}
								if (shape.datas[i] < chart.volMinRight) {
									chart.volMinRight = shape.datas[i];
								}
							}
						}
					} else if (shape.divIndex == 2) {
						if (!load3 && i == chart.firstVisibleIndex) {
							if (shape.leftOrRight) {
								chart.indMax = shape.datas[i];
								chart.indMin = shape.datas[i];
							} else {
								chart.indMaxRight = shape.datas[i];
								chart.indMinRight = shape.datas[i];
							}
							load3 = true;
						} else {
							if (shape.leftOrRight) {
								if (shape.datas[i] > chart.indMax) {
									chart.indMax = shape.datas[i];
								}
								if (shape.datas[i] < chart.indMin) {
									chart.indMin = shape.datas[i];
								}
							} else {
								if (shape.datas[i] > chart.indMaxRight) {
									chart.indMaxRight = shape.datas[i];
								}
								if (shape.datas[i] < chart.indMinRight) {
									chart.indMinRight = shape.datas[i];
								}
							}
						}
					} else if (shape.divIndex == 3) {
						if (!load4 && i == chart.firstVisibleIndex) {
							if (shape.leftOrRight) {
								chart.indMax2 = shape.datas[i];
								chart.indMin2 = shape.datas[i];
							} else {
								chart.indMax2Right = shape.datas[i];
								chart.indMin2Right = shape.datas[i];
							}
							load4 = true;
						} else {
							if (shape.leftOrRight) {
								if (shape.datas[i] > chart.indMax2) {
									chart.indMax2 = shape.datas[i];
								}
								if (shape.datas[i] < chart.indMin2) {
									chart.indMin2 = shape.datas[i];
								}
							} else {
								if (shape.datas[i] > chart.indMax2Right) {
									chart.indMax2Right = shape.datas[i];
								}
								if (shape.datas[i] < chart.indMin2Right) {
									chart.indMin2Right = shape.datas[i];
								}
							}
						}
					}
				}
			}
			if (shape.datas2.length > 0) {
				for (let i = chart.firstVisibleIndex; i <= lastValidIndex; i++) {
					if (shape.divIndex == 0) {
						if (shape.leftOrRight) {
							if (shape.datas2[i] > chart.candleMax) {
								chart.candleMax = shape.datas2[i];
							}
							if (shape.datas2[i] < chart.candleMin) {
								chart.candleMin = shape.datas2[i];
							}
						} else {
							if (shape.datas2[i] > chart.candleMaxRight) {
								chart.candleMaxRight = shape.datas2[i];
							}
							if (shape.datas2[i] < chart.candleMinRight) {
								chart.candleMinRight = shape.datas2[i];
							}
						}
					} else if (shape.divIndex == 1) {
						if (shape.leftOrRight) {
							if (shape.datas2[i] > chart.volMax) {
								chart.volMax = shape.datas2[i];
							}
							if (shape.datas2[i] < chart.volMin) {
								chart.volMin = shape.datas2[i];
							}
						} else {
							if (shape.datas2[i] > chart.volMaxRight) {
								chart.volMaxRight = shape.datas2[i];
							}
							if (shape.datas2[i] < chart.volMinRight) {
								chart.volMinRight = shape.datas2[i];
							}
						}
					} else if (shape.divIndex == 2) {
						if (shape.leftOrRight) {
							if (shape.datas2[i] > chart.indMax) {
								chart.indMax = shape.datas2[i];
							}
							if (shape.datas2[i] < chart.indMin) {
								chart.indMin = shape.datas2[i];
							}
						} else {
							if (shape.datas2[i] > chart.indMaxRight) {
								chart.indMaxRight = shape.datas2[i];
							}
							if (shape.datas2[i] < chart.indMinRight) {
								chart.indMinRight = shape.datas2[i];
							}
						}
					} else if (shape.divIndex == 3) {
						if (shape.leftOrRight) {
							if (shape.datas2[i] > chart.indMax2) {
								chart.indMax2 = shape.datas2[i];
							}
							if (shape.datas2[i] < chart.indMin2) {
								chart.indMin2 = shape.datas2[i];
							}
						} else {
							if (shape.datas2[i] > chart.indMax2Right) {
								chart.indMax2Right = shape.datas2[i];
							}
							if (shape.datas2[i] < chart.indMin2Right) {
								chart.indMin2Right = shape.datas2[i];
							}
						}
					}
				}
			}
		}
	}
	if (isTrend) {
		let subMax = Math.max(Math.abs(chart.candleMax - firstOpen), Math.abs(chart.candleMin - firstOpen));
		chart.candleMax = firstOpen + subMax;
		chart.candleMin = firstOpen - subMax;
	} else {
		if (chart.candleMax == 0 && chart.candleMin == 0) {
			chart.candleMax = 1;
			chart.candleMin = -1;
		}
		if (chart.volMax == 0 && chart.volMin == 0) {
			chart.volMax = 1;
			chart.volMin = -1;
		}
		if (chart.indMax == 0 && chart.indMin == 0) {
			chart.indMax = 1;
			chart.indMin = -1;
		}
		if (chart.indMax2 == 0 && chart.indMin2 == 0) {
			chart.indMax2 = 1;
			chart.indMin2 = -1;
		}
		if (chart.candleMaxRight == 0 && chart.candleMinRight == 0) {
			chart.candleMaxRight = 1;
			chart.candleMinRight = -1;
		}
		if (chart.volMaxRight == 0 && chart.volMinRight == 0) {
			chart.volMaxRight = 1;
			chart.volMinRight = -1;
		}
		if (chart.indMaxRight == 0 && chart.indMinRight == 0) {
			chart.indMaxRight = 1;
			chart.indMinRight = -1;
		}
		if (chart.indMax2Right == 0 && chart.indMin2Right == 0) {
			chart.indMax2Right = 1;
			chart.indMin2Right = -1;
		}
	}
}

/*
* 绘制线条
* chart:图表
* paint:绘图对象
* clipRect:裁剪区域
* divIndex:图层
* datas:数据
* color:颜色
* selected:是否选中
*/
function drawChartLines(chart : FCChart, paint : FCPaint, clipRect : FCRect, divIndex : number, datas : Array<number>, color : string, selected : boolean) {
	paint.beginPath();
	let lastX = 0, lastY = 0;
	let maxVisibleRecord = getChartMaxVisibleCount(chart, chart.hScalePixel, getChartWorkAreaWidth(chart));
	let lastValidIndex = chart.lastVisibleIndex;
	if (chart.lastValidIndex != -1) {
		lastValidIndex = chart.lastValidIndex;
	}
	for (let i = chart.firstVisibleIndex; i <= lastValidIndex; i++) {
		let x = getChartX(chart, i);
		let value = datas[i];
		let y = getChartY(chart, divIndex, value);
		if (i > chart.firstVisibleIndex) {
			paint.addLine(lastX, lastY, x, y);
		}
		lastX = x;
		lastY = y;
		if (selected) {
			let kPInterval = Math.floor(maxVisibleRecord / 30);
			if (kPInterval < 2) {
				kPInterval = 3;
			}
			if (i % kPInterval == 0) {
				paint.fillRect(color, x - 3, y - 3, x + 3, y + 3);
			}
		}
	}
	paint.drawPath(color, chart.lineWidthChart, null);
	paint.closePath();
}

/*
* 绘制线条到右轴
* chart:图表
* paint:绘图对象
* clipRect:裁剪区域
* divIndex:图层
* datas:数据
* color:颜色
* selected:是否选中
*/
function drawChartLinesInRight(chart : FCChart, paint : FCPaint, clipRect : FCRect, divIndex : number, datas : Array<number>, color : string, selected : boolean) {
	paint.beginPath();
	let lastX = 0, lastY = 0;
	let maxVisibleRecord = getChartMaxVisibleCount(chart, chart.hScalePixel, getChartWorkAreaWidth(chart));
	let lastValidIndex = chart.lastVisibleIndex;
	if (chart.lastValidIndex != -1) {
		lastValidIndex = chart.lastValidIndex;
	}
	for (let i = chart.firstVisibleIndex; i <= lastValidIndex; i++) {
		let x = getChartX(chart, i);
		let value = datas[i];
		let y = getChartYInRight(chart, divIndex, value);
		if (i > chart.firstVisibleIndex) {
			paint.addLine(lastX, lastY, x, y);
		}
		lastX = x;
		lastY = y;
		if (selected) {
			let kPInterval = Math.floor(maxVisibleRecord / 30);
			if (kPInterval < 2) {
				kPInterval = 3;
			}
			if (i % kPInterval == 0) {
				paint.fillRect(color, x - 3, y - 3, x + 3, y + 3);
			}
		}
	}
	paint.drawPath(color, chart.lineWidthChart, null);
	paint.closePath();
}

/*
* 绘制图表
* chart:图表
* paint:绘图对象
* clipRect:裁剪区域
*/
function drawChartStock(chart : FCChart, paint : FCPaint, clipRect : FCRect) {
	let lastValidIndex = chart.lastVisibleIndex;
	let cWidth = Math.floor(chart.hScalePixel - 3) / 2;
	if (cWidth < 0) {
		cWidth = 0;
	}
	if (chart.data != null && chart.data.length > 0) {
		let candleHeight = getCandleDivHeight(chart);
		let volHeight = getVolDivHeight(chart);
		let indHeight = getIndDivHeight(chart);
		let isTrend = chart.cycle == "trend";
		if (chart.lastValidIndex != -1) {
			lastValidIndex = chart.lastValidIndex;
		}
		let maxVisibleRecord = getChartMaxVisibleCount(chart, chart.hScalePixel, getChartWorkAreaWidth(chart));
		paint.save();
		paint.setClip(chart.leftVScaleWidth, 0, chart.size.cx - chart.rightVScaleWidth, candleHeight);
		if (isTrend) {
			paint.beginPath();
			let lastX = 0, lastY = 0;
			for (let i = chart.firstVisibleIndex; i <= lastValidIndex; i++) {
				let x = getChartX(chart, i);
				let close = chart.data[i].close;
				let closeY = getChartY(chart, 0, close);
				if (i > chart.firstVisibleIndex) {
					paint.addLine(lastX, lastY, x, closeY)
				}
				lastX = x;
				lastY = closeY;
			}
			paint.drawPath(chart.indicatorColors[7], chart.lineWidthChart, null);
			paint.closePath();
		}
		let hasMinTag = false, hasMaxTag = false;
		for (let i = chart.firstVisibleIndex; i <= lastValidIndex; i++) {
			let x = getChartX(chart, i);
			let open = chart.data[i].open;
			let close = chart.data[i].close;
			let high = chart.data[i].high;
			let low = chart.data[i].low;
			let openY = getChartY(chart, 0, open);
			let closeY = getChartY(chart, 0, close);
			let highY = getChartY(chart, 0, high);
			let lowY = getChartY(chart, 0, low);
			if (close >= open) {
				if (isTrend) {
				} else {
					paint.drawLine(chart.upColor, chart.lineWidthChart, null, x, highY, x, lowY);
					if (cWidth > 0) {
						if (close == open) {
							paint.drawLine(chart.upColor, chart.lineWidthChart, null, x - cWidth, closeY, x + cWidth, closeY);
						}
						else {
							paint.fillRect(chart.upColor, x - cWidth, closeY, x + cWidth, openY);
						}
					}
				}
			} else {
				if (isTrend) {
				} else {
					paint.drawLine(chart.downColor, chart.lineWidthChart, null, x, highY, x, lowY);
					if (cWidth > 0) {
						paint.fillRect(chart.downColor, x - cWidth, openY, x + cWidth, closeY);
					}
				}
			}
			if (chart.selectShape == "CANDLE") {
				let kPInterval = Math.floor(maxVisibleRecord / 30);
				if (kPInterval < 2) {
					kPInterval = 3;
				}
				if (i % kPInterval == 0) {
					if (isTrend) {
					} else {
						paint.fillRect(chart.indicatorColors[0], x - 3, closeY - 3, x + 3, closeY + 3);
					}
				}
			}
			if (!isTrend) {
				if (!hasMaxTag) {
					if (high == chart.candleMax) {
						let tag = high.toFixed(chart.candleDigit);
						let tSize = paint.textSize(tag, chart.font);
						paint.drawText(tag, chart.textColor, chart.font, x - tSize.cx / 2, highY - tSize.cy - 2);
						hasMaxTag = true;
					}
				}
				if (!hasMinTag) {
					if (low == chart.candleMin) {
						let tag = low.toFixed(chart.candleDigit);
						let tSize = paint.textSize(tag, chart.font);
						paint.drawText(tag, chart.textColor, chart.font, x - tSize.cx / 2, lowY + 2);
						hasMinTag = true;
					}
				}
			}
		}
		paint.restore();
		for (let i = chart.firstVisibleIndex; i <= lastValidIndex; i++) {
			let x = getChartX(chart, i);
			let open = chart.data[i].open;
			let close = chart.data[i].close;
			let openY = getChartY(chart, 0, open);
			let closeY = getChartY(chart, 0, close);
			let volY = 0;
			let zeroY = 0;
			if (volHeight > 0) {
				let volume = chart.data[i].volume;
				volY = getChartY(chart, 1, volume);
				zeroY = getChartY(chart, 1, 0);
			}
			if (close >= open) {
				if (isTrend) {
					if (volHeight > 0) {
						paint.drawLine(chart.indicatorColors[6], chart.lineWidthChart, null, x, volY, x, zeroY);
					}
				} else {
					if (cWidth > 0) {
						if (volHeight > 0) {
							paint.fillRect(chart.upColor, x - cWidth, volY, x + cWidth, zeroY);
						}
					} else {
						if (volHeight > 0) {
							paint.drawLine(chart.upColor, chart.lineWidthChart, null, x - cWidth, volY, x + cWidth, zeroY);
						}
					}
				}
			} else {
				if (isTrend) {
					if (volHeight > 0) {
						paint.drawLine(chart.indicatorColors[6], chart.lineWidthChart, null, x, volY, x, zeroY);
					}
				} else {
					if (cWidth > 0) {
						if (volHeight > 0) {
							paint.fillRect(chart.downColor, x - cWidth, volY, x + cWidth, zeroY);
						}
					} else {
						if (volHeight > 0) {
							paint.drawLine(chart.downColor, chart.lineWidthChart, null, x - cWidth, volY, x + cWidth, zeroY);
						}
					}
				}
			}
			if (chart.selectShape == "VOL") {
				let kPInterval = Math.floor(maxVisibleRecord / 30);
				if (kPInterval < 2) {
					kPInterval = 3;
				}
				if (i % kPInterval == 0) {
					paint.fillRect(chart.indicatorColors[0], x - 3, volY - 3, x + 3, volY + 3);
				}
			}
		}
		if (!isTrend) {
			paint.save();
			paint.setClip(chart.leftVScaleWidth, 20, chart.size.cx - chart.rightVScaleWidth, candleHeight);
			if (chart.mainIndicator == "BOLL") {
				drawChartLines(chart, paint, clipRect, 0, chart.bollMid, chart.indicatorColors[0], (chart.selectShape == chart.mainIndicator && chart.selectShapeEx == "MID") ? true : false);
				drawChartLines(chart, paint, clipRect, 0, chart.bollUp, chart.indicatorColors[1], (chart.selectShape == chart.mainIndicator && chart.selectShapeEx == "UP") ? true : false);
				drawChartLines(chart, paint, clipRect, 0, chart.bollDown, chart.indicatorColors[2], (chart.selectShape == chart.mainIndicator && chart.selectShapeEx == "DOWN") ? true : false);
			} else if (chart.mainIndicator == "MA") {
				drawChartLines(chart, paint, clipRect, 0, chart.ma5, chart.indicatorColors[0], (chart.selectShape == chart.mainIndicator && chart.selectShapeEx == "5") ? true : false);
				drawChartLines(chart, paint, clipRect, 0, chart.ma10, chart.indicatorColors[1], (chart.selectShape == chart.mainIndicator && chart.selectShapeEx == "10") ? true : false);
				drawChartLines(chart, paint, clipRect, 0, chart.ma20, chart.indicatorColors[2], (chart.selectShape == chart.mainIndicator && chart.selectShapeEx == "20") ? true : false);
				drawChartLines(chart, paint, clipRect, 0, chart.ma30, chart.indicatorColors[5], (chart.selectShape == chart.mainIndicator && chart.selectShapeEx == "30") ? true : false);
				drawChartLines(chart, paint, clipRect, 0, chart.ma120, chart.indicatorColors[4], (chart.selectShape == chart.mainIndicator && chart.selectShapeEx == "120") ? true : false);
				drawChartLines(chart, paint, clipRect, 0, chart.ma250, chart.indicatorColors[3], (chart.selectShape == chart.mainIndicator && chart.selectShapeEx == "250") ? true : false);
			}
			paint.restore();
		}
		if (indHeight > 0) {
			if (chart.showIndicator == "MACD") {
				let zeroY = getChartY(chart, 2, 0);
				paint.drawLine(chart.indicatorColors[4], chart.lineWidthChart, null, chart.leftVScaleWidth, zeroY, getChartX(chart, chart.lastVisibleIndex), zeroY);
				for (let i = chart.firstVisibleIndex; i <= lastValidIndex; i++) {
					let x = getChartX(chart, i);
					let macd = chart.allmacdarr[i];
					let macdY = getChartY(chart, 2, macd);
					if (macdY < zeroY) {
						paint.drawLine(chart.indicatorColors[3], chart.lineWidthChart, null, x, macdY, x, zeroY);
					} else {
						paint.drawLine(chart.indicatorColors[4], chart.lineWidthChart, null, x, macdY, x, zeroY);
					}
					if (chart.selectShape == chart.showIndicator && chart.selectShapeEx == "MACD") {
						let kPInterval = Math.floor(maxVisibleRecord / 30);
						if (kPInterval < 2) {
							kPInterval = 3;
						}
						if (i % kPInterval == 0) {
							paint.fillRect(chart.indicatorColors[4], x - 3, macdY - 3, x + 3, macdY + 3);
						}
					}
				}
				drawChartLines(chart, paint, clipRect, 2, chart.alldifarr, chart.indicatorColors[0], (chart.selectShape == chart.showIndicator && chart.selectShapeEx == "DIF") ? true : false);
				drawChartLines(chart, paint, clipRect, 2, chart.alldeaarr, chart.indicatorColors[1], (chart.selectShape == chart.showIndicator && chart.selectShapeEx == "DEA") ? true : false);
			} else if (chart.showIndicator == "KDJ") {
				drawChartLines(chart, paint, clipRect, 2, chart.kdjK, chart.indicatorColors[0], (chart.selectShape == chart.showIndicator && chart.selectShapeEx == "K") ? true : false);
				drawChartLines(chart, paint, clipRect, 2, chart.kdjD, chart.indicatorColors[1], (chart.selectShape == chart.showIndicator && chart.selectShapeEx == "D") ? true : false);
				drawChartLines(chart, paint, clipRect, 2, chart.kdjJ, chart.indicatorColors[2], (chart.selectShape == chart.showIndicator && chart.selectShapeEx == "J") ? true : false);
			} else if (chart.showIndicator == "RSI") {
				drawChartLines(chart, paint, clipRect, 2, chart.rsi1, chart.indicatorColors[5], (chart.selectShape == chart.showIndicator && chart.selectShapeEx == "6") ? true : false);
				drawChartLines(chart, paint, clipRect, 2, chart.rsi2, chart.indicatorColors[1], (chart.selectShape == chart.showIndicator && chart.selectShapeEx == "12") ? true : false);
				drawChartLines(chart, paint, clipRect, 2, chart.rsi3, chart.indicatorColors[2], (chart.selectShape == chart.showIndicator && chart.selectShapeEx == "24") ? true : false);
			}
			else if (chart.showIndicator == "BIAS") {
				drawChartLines(chart, paint, clipRect, 2, chart.bias1, chart.indicatorColors[5], (chart.selectShape == chart.showIndicator && chart.selectShapeEx == "1") ? true : false);
				drawChartLines(chart, paint, clipRect, 2, chart.bias2, chart.indicatorColors[1], (chart.selectShape == chart.showIndicator && chart.selectShapeEx == "2") ? true : false);
				drawChartLines(chart, paint, clipRect, 2, chart.bias3, chart.indicatorColors[2], (chart.selectShape == chart.showIndicator && chart.selectShapeEx == "3") ? true : false);
			}
			else if (chart.showIndicator == "ROC") {
				drawChartLines(chart, paint, clipRect, 2, chart.roc, chart.indicatorColors[0], (chart.selectShape == chart.showIndicator && chart.selectShapeEx == "ROC") ? true : false);
				drawChartLines(chart, paint, clipRect, 2, chart.rocMa, chart.indicatorColors[1], (chart.selectShape == chart.showIndicator && chart.selectShapeEx == "ROCMA") ? true : false);
			} else if (chart.showIndicator == "WR") {
				drawChartLines(chart, paint, clipRect, 2, chart.wr1, chart.indicatorColors[0], (chart.selectShape == chart.showIndicator && chart.selectShapeEx == "1") ? true : false);
				drawChartLines(chart, paint, clipRect, 2, chart.wr2, chart.indicatorColors[1], (chart.selectShape == chart.showIndicator && chart.selectShapeEx == "2") ? true : false);
			} else if (chart.showIndicator == "CCI") {
				drawChartLines(chart, paint, clipRect, 2, chart.cci, chart.indicatorColors[0], (chart.selectShape == chart.showIndicator) ? true : false);
			} else if (chart.showIndicator == "BBI") {
				drawChartLines(chart, paint, clipRect, 2, chart.bbi, chart.indicatorColors[0], (chart.selectShape == chart.showIndicator) ? true : false);
			} else if (chart.showIndicator == "TRIX") {
				drawChartLines(chart, paint, clipRect, 2, chart.trix, chart.indicatorColors[0], (chart.selectShape == chart.showIndicator && chart.selectShapeEx == "TRIX") ? true : false);
				drawChartLines(chart, paint, clipRect, 2, chart.trixMa, chart.indicatorColors[1], (chart.selectShape == chart.showIndicator && chart.selectShapeEx == "TRIXMA") ? true : false);
			} else if (chart.showIndicator == "DMA") {
				drawChartLines(chart, paint, clipRect, 2, chart.dma1, chart.indicatorColors[0], (chart.selectShape == chart.showIndicator && chart.selectShapeEx == "DIF") ? true : false);
				drawChartLines(chart, paint, clipRect, 2, chart.dma2, chart.indicatorColors[1], (chart.selectShape == chart.showIndicator && chart.selectShapeEx == "DIFMA") ? true : false);
			}
		}
	}
	//绘制扩展线条
	if (chart.shapes.length > 0) {
		for (let i = 0; i < chart.shapes.length; i++) {
			let shape = chart.shapes[i]
			if (shape.shapeType == "bar") {
				for (let j = chart.firstVisibleIndex; j <= lastValidIndex; j++) {
					if (shape.showHideDatas.length > j && shape.showHideDatas[j].toString() == "0") {
						continue
					}
					let x = getChartX(chart, j);
					let y1 = 0;
					if (shape.leftOrRight) {
						y1 = getChartY(chart, shape.divIndex, shape.datas[j]);
					} else {
						y1 = getChartYInRight(chart, shape.divIndex, shape.datas[j]);
					}
					if (shape.style != "2color") {
						let y2 = 0;
						if (shape.leftOrRight) {
							y2 = getChartY(chart, shape.divIndex, shape.datas2[j]);
						} else {
							y2 = getChartYInRight(chart, shape.divIndex, shape.datas2[j]);
						}
						if (y1 >= y2) {
							paint.fillRect(shape.color!, x - cWidth, y2, x + cWidth, y1);
						}
						else {
							paint.fillRect(shape.color!, x - cWidth, y1, x + cWidth, y2);
						}
					} else {
						let y2 = 0;
						if (shape.leftOrRight) {
							y2 = getChartY(chart, shape.divIndex, 0);
						} else {
							y2 = getChartYInRight(chart, shape.divIndex, 0);
						}
						if (y1 >= y2) {
							paint.drawLine(shape.color2!, 1, null, x, y1, x, y2);
						}
						else {
							paint.drawLine(shape.color!, 1, null, x, y1, x, y2);
						}
						if (j == lastValidIndex) {
							paint.drawLine(shape.color2!, 1, null, chart.leftVScaleWidth, y2, chart.size.cx - chart.rightVScaleWidth, y2);
						}
					}
				}
			}
			else if (shape.shapeType == "text") {
				for (let j = chart.firstVisibleIndex; j <= lastValidIndex; j++) {
					let x = getChartX(chart, j);
					if (shape.datas[j] != 0) {
						let y1 = 0;
						if (shape.leftOrRight) {
							y1 = getChartY(chart, shape.divIndex, shape.value);
						} else {
							y1 = getChartYInRight(chart, shape.divIndex, shape.value);
						}
						let drawText = shape.text;
						let tSize = paint.textSize(drawText, "Default,12");
						paint.drawText(drawText, shape.color!, "Default,12", x - tSize.cx / 2, y1);
					}
				}
			}
			else {
				if (shape.leftOrRight) {
					drawChartLines(chart, paint, clipRect, shape.divIndex, shape.datas, shape.color!, (chart.selectShape == shape.shapeName) ? true : false);
				} else {
					drawChartLinesInRight(chart, paint, clipRect, shape.divIndex, shape.datas, shape.color!, (chart.selectShape == shape.shapeName) ? true : false);
				}
			}
		}
	}
}

/*
* 获取数据
* chart:图表
*/
function calcChartIndicator(chart : FCChart) {
	clearDataArr(chart)
	if (chart.data.length > 0) {
		let closeArr : Array<number> = [];
		let highArr : Array<number> = [];
		let lowArr : Array<number> = [];
		if (chart.data.length > 0) {
			for (let i = 0; i < chart.data.length; i++) {
				closeArr.push(chart.data[i].close)
				highArr.push(chart.data[i].high)
				lowArr.push(chart.data[i].low)
			}
		}
		chart.closeArr = closeArr;
		if (chart.mainIndicator == "BOLL") {
			getBollData(closeArr, 20, chart.bollUp, chart.bollMid, chart.bollDown);
		} else if (chart.mainIndicator == "MA") {
			chart.ma5 = maValue(closeArr, 5);
			chart.ma10 = maValue(closeArr, 10);
			chart.ma20 = maValue(closeArr, 20);
			chart.ma30 = maValue(closeArr, 30);
			chart.ma120 = maValue(closeArr, 120);
			chart.ma250 = maValue(closeArr, 250);
		}
		if (chart.showIndicator == "BIAS") {
			getBIASData(closeArr, 6, 12, 24, chart.bias1, chart.bias2, chart.bias3);
		}
		else if (chart.showIndicator == "DMA") {
			getDMAData(closeArr, 10, 50, chart.dma1, chart.dma2);
		}
		else if (chart.showIndicator == "BBI") {
			getBBIData(closeArr, 3, 6, 12, 24, chart.bbi);
		}
		else if (chart.showIndicator == "RSI") {
			getRSIData(closeArr, 6, 12, 24, chart.rsi1, chart.rsi2, chart.rsi3);
		}
		else if (chart.showIndicator == "ROC") {
			getRocData(closeArr, 12, 6, chart.roc, chart.rocMa);
		}
		else if (chart.showIndicator == "TRIX") {
			getTRIXData(closeArr, 9, chart.trix, chart.trixMa);
		}
		else if (chart.showIndicator == "KDJ") {
			getKDJData(highArr, lowArr, closeArr, 9, 3, 3, chart.kdjK, chart.kdjD, chart.kdjJ);
		}
		else if (chart.showIndicator == "WR") {
			getWRData(highArr, lowArr, closeArr, 5, 10, chart.wr1, chart.wr2);
		}
		else if (chart.showIndicator == "CCI") {
			getCCIData(highArr, lowArr, closeArr, 14, chart.cci);
		} else if (chart.showIndicator == "MACD") {
			//缓存MACD数据
			chart.allema12.push(closeArr[0]);
			chart.allema26.push(closeArr[0]);
			chart.alldeaarr.push(0);
			for (let i = 1; i < closeArr.length; i++) {
				chart.allema12.push(getEMA(12, closeArr[i], chart.allema12[i - 1]));
				chart.allema26.push(getEMA(26, closeArr[i], chart.allema26[i - 1]));
			}
			chart.alldifarr = getDIF(chart.allema12, chart.allema26);
			for (let i = 1; i < chart.alldifarr.length; i++) {
				chart.alldeaarr.push(chart.alldeaarr[i - 1] * 8 / 10 + chart.alldifarr[i] * 2 / 10);
			}
			chart.allmacdarr = getMACD(chart.alldifarr, chart.alldeaarr);
		}
		calculateChartMaxMin(chart);
	}
	calculateChartMaxMin(chart)
}

/*
* 计算EMA
* n:周期
* value:当前数据
* lastEMA:上期数据
*/
function getEMA(n : number, value : number, lastEMA : number) : number {
	return (value * 2 + lastEMA * (n - 1)) / (n + 1);
}

/*
* 计算MACD
* dif:DIF数据
* dea:DEA数据
*/
function getMACD(dif : Array<number>, dea : Array<number>) : Array<number> {
	let result : Array<number> = [];
	for (let i = 0; i < dif.length; i++) {
		result.push((dif[i] - dea[i]) * 2);
	}
	return result;
}

/*
* 计算DIF
* close12:12日数据
* close26:26日数据
*/
function getDIF(close12 : Array<number>, close26 : Array<number>) : Array<number> {
	let result : Array<number> = [];
	for (let i = 0; i < close12.length; i++) {
		result.push(close12[i] - close26[i]);
	}
	return result;
}

/*
* 清除缓存数据方法
* chart:图表
*/
function clearDataArr(chart : FCChart) {
	chart.allema12 = [];
	chart.allema26 = [];
	chart.alldifarr = [];
	chart.alldeaarr = [];
	chart.allmacdarr = [];
	chart.bollUp = [];
	chart.bollDown = [];
	chart.bollMid = [];
	chart.bias1 = [];
	chart.bias2 = [];
	chart.bias3 = [];
	chart.kdjK = [];
	chart.kdjD = [];
	chart.kdjJ = [];
	chart.rsi1 = [];
	chart.rsi2 = [];
	chart.rsi3 = [];
	chart.roc = [];
	chart.rocMa = [];
	chart.wr1 = [];
	chart.wr2 = [];
	chart.cci = [];
	chart.bbi = [];
	chart.trix = [];
	chart.trixMa = [];
	chart.dma1 = [];
	chart.dma2 = [];
	chart.ma5 = [];
	chart.ma10 = [];
	chart.ma20 = [];
	chart.ma30 = [];
	chart.ma120 = [];
	chart.ma250 = [];
}

/*
* 判断是否选中线条
* chart:图表
* mp:坐标
* divIndex:层索引
* datas:数据
* curIndex:当前索引
*/
function selectLines(chart : FCChart, mp : FCPoint, divIndex : number, datas : Array<number>, curIndex : number) : boolean {
	if (datas.length > 0) {
		let topY = getChartY(chart, divIndex, datas[curIndex]);
		if (chart.hScalePixel <= 1) {
			if (mp.y >= topY - 8 && mp.y <= topY + 8) {
				return true;
			}
		} else {
			let index = curIndex;
			let scaleX = getChartX(chart, index);
			let judgeTop = 0;
			let judgeScaleX = scaleX;
			if (mp.x >= scaleX) {
				let leftIndex = curIndex + 1;
				if (curIndex < chart.lastVisibleIndex) {
					let rightValue = datas[leftIndex];
					judgeTop = getChartY(chart, divIndex, rightValue);
				}
				else {
					judgeTop = topY;
				}
			}
			else {
				judgeScaleX = scaleX - chart.hScalePixel;
				let rightIndex = curIndex - 1;
				if (curIndex > 0) {
					let leftValue = datas[rightIndex];
					judgeTop = getChartY(chart, divIndex, leftValue);
				} else {
					judgeTop = topY;
				}
			}
			let lineWidth = 4;
			let judgeX = 0, judgeY = 0, judgeW = 0, judgeH = 0;
			if (judgeTop >= topY) {
				judgeX = judgeScaleX;
				judgeY = topY - 2 - lineWidth;
				judgeW = chart.hScalePixel;
				judgeH = judgeTop - topY + lineWidth < 4 ? 4 : judgeTop - topY + 4 + lineWidth;
			}
			else {
				judgeX = judgeScaleX;
				judgeY = judgeTop - 2 - lineWidth / 2;
				judgeW = chart.hScalePixel;
				judgeH = topY - judgeTop + lineWidth < 4 ? 4 : topY - judgeTop + 4 + lineWidth;
			}

			if (mp.x >= judgeX && mp.x <= judgeX + judgeW && mp.y >= judgeY && mp.y <= judgeY + judgeH) {

				return true;
			}
		}
	}
	return false;
}

/*
* 判断是否在右轴选中线条
* chart:图表
* mp:坐标
* divIndex:层索引
* datas:数据
* curIndex:当前索引
*/
function selectLinesInRight(chart : FCChart, mp : FCPoint, divIndex : number, datas : Array<number>, curIndex : number) : boolean {
	if (datas.length > 0) {
		let topY = getChartYInRight(chart, divIndex, datas[curIndex]);
		if (chart.hScalePixel <= 1) {
			if (mp.y >= topY - 8 && mp.y <= topY + 8) {
				return true;
			}
		} else {
			let index = curIndex;
			let scaleX = getChartX(chart, index);
			let judgeTop = 0;
			let judgeScaleX = scaleX;
			if (mp.x >= scaleX) {
				let leftIndex = curIndex + 1;
				if (curIndex < chart.lastVisibleIndex) {
					let rightValue = datas[leftIndex];
					judgeTop = getChartYInRight(chart, divIndex, rightValue);
				}
				else {
					judgeTop = topY;
				}
			}
			else {
				judgeScaleX = scaleX - chart.hScalePixel;
				let rightIndex = curIndex - 1;
				if (curIndex > 0) {
					let leftValue = datas[rightIndex];
					judgeTop = getChartYInRight(chart, divIndex, leftValue);
				} else {
					judgeTop = topY;
				}
			}
			let lineWidth = 4;
			let judgeX = 0, judgeY = 0, judgeW = 0, judgeH = 0;
			if (judgeTop >= topY) {
				judgeX = judgeScaleX;
				judgeY = topY - 2 - lineWidth;
				judgeW = chart.hScalePixel;
				judgeH = judgeTop - topY + lineWidth < 4 ? 4 : judgeTop - topY + 4 + lineWidth;
			}
			else {
				judgeX = judgeScaleX;
				judgeY = judgeTop - 2 - lineWidth / 2;
				judgeW = chart.hScalePixel;
				judgeH = topY - judgeTop + lineWidth < 4 ? 4 : topY - judgeTop + 4 + lineWidth;
			}

			if (mp.x >= judgeX && mp.x <= judgeX + judgeW && mp.y >= judgeY && mp.y <= judgeY + judgeH) {

				return true;
			}
		}
	}
	return false;
}

/*
* 判断是否选中图形
* chart:图表
* mp:坐标
*/
function selectShape(chart : FCChart, mp : FCPoint) {
	chart.selectShape = "";
	chart.selectShapeEx = "";
	let candleHeight = getCandleDivHeight(chart);
	let volHeight = getVolDivHeight(chart);
	let indHeight = getIndDivHeight(chart);
	let index = getChartIndex(chart, mp);
	if (mp.y >= candleHeight + volHeight && mp.y <= candleHeight + volHeight + indHeight) {
		if (chart.showIndicator == "MACD") {
			let macdY = getChartY(chart, 2, chart.allmacdarr[index]);
			let zeroY = getChartY(chart, 2, 0);
			if (selectLines(chart, mp, 2, chart.allmacdarr, index)) {
				chart.selectShape = chart.showIndicator;
				chart.selectShapeEx = "MACD";
			}
			if (selectLines(chart, mp, 2, chart.alldifarr, index)) {
				chart.selectShape = chart.showIndicator;
				chart.selectShapeEx = "DIF";
			}
			else if (selectLines(chart, mp, 2, chart.alldeaarr, index)) {
				chart.selectShape = chart.showIndicator;
				chart.selectShapeEx = "DEA";
			}
		} else if (chart.showIndicator == "KDJ") {
			if (selectLines(chart, mp, 2, chart.kdjK, index)) {
				chart.selectShape = chart.showIndicator;
				chart.selectShapeEx = "K";
			}
			else if (selectLines(chart, mp, 2, chart.kdjD, index)) {
				chart.selectShape = chart.showIndicator;
				chart.selectShapeEx = "D";
			} else if (selectLines(chart, mp, 2, chart.kdjJ, index)) {
				chart.selectShape = chart.showIndicator;
				chart.selectShapeEx = "J";
			}
		} else if (chart.showIndicator == "RSI") {
			if (selectLines(chart, mp, 2, chart.rsi1, index)) {
				chart.selectShape = chart.showIndicator;
				chart.selectShapeEx = "6";
			}
			else if (selectLines(chart, mp, 2, chart.rsi2, index)) {
				chart.selectShape = chart.showIndicator;
				chart.selectShapeEx = "12";
			} else if (selectLines(chart, mp, 2, chart.rsi3, index)) {
				chart.selectShape = chart.showIndicator;
				chart.selectShapeEx = "24";
			}
		}
		else if (chart.showIndicator == "BIAS") {
			if (selectLines(chart, mp, 2, chart.bias1, index)) {
				chart.selectShape = chart.showIndicator;
				chart.selectShapeEx = "1";
			}
			else if (selectLines(chart, mp, 2, chart.bias2, index)) {
				chart.selectShape = chart.showIndicator;
				chart.selectShapeEx = "2";
			} else if (selectLines(chart, mp, 2, chart.bias3, index)) {
				chart.selectShape = chart.showIndicator;
				chart.selectShapeEx = "3";
			}
		}
		else if (chart.showIndicator == "ROC") {
			if (selectLines(chart, mp, 2, chart.roc, index)) {
				chart.selectShape = chart.showIndicator;
				chart.selectShapeEx = "ROC";
			}
			else if (selectLines(chart, mp, 2, chart.rocMa, index)) {
				chart.selectShape = chart.showIndicator;
				chart.selectShapeEx = "ROCMA";
			}
		} else if (chart.showIndicator == "WR") {
			if (selectLines(chart, mp, 2, chart.wr1, index)) {
				chart.selectShape = chart.showIndicator;
				chart.selectShapeEx = "1";
			}
			else if (selectLines(chart, mp, 2, chart.wr2, index)) {
				chart.selectShape = "WR";
				chart.selectShapeEx = "2";
			}
		} else if (chart.showIndicator == "CCI") {
			if (selectLines(chart, mp, 2, chart.cci, index)) {
				chart.selectShape = chart.showIndicator;
			}
		} else if (chart.showIndicator == "BBI") {
			if (selectLines(chart, mp, 2, chart.bbi, index)) {
				chart.selectShape = chart.showIndicator;
			}
		} else if (chart.showIndicator == "TRIX") {
			if (selectLines(chart, mp, 2, chart.trix, index)) {
				chart.selectShape = chart.showIndicator;
				chart.selectShapeEx = "TRIX";
			}
			else if (selectLines(chart, mp, 2, chart.trixMa, index)) {
				chart.selectShape = chart.showIndicator;
				chart.selectShapeEx = "TRIXMA";
			}
		} else if (chart.showIndicator == "DMA") {
			if (selectLines(chart, mp, 2, chart.dma1, index)) {
				chart.selectShape = chart.showIndicator;
				chart.selectShapeEx = "DIF";
			}
			else if (selectLines(chart, mp, 2, chart.dma2, index)) {
				chart.selectShape = chart.showIndicator;
				chart.selectShapeEx = "DIFMA";
			}
		}
	}
	else if (mp.y >= candleHeight && mp.y <= candleHeight + volHeight) {
		let volY = getChartY(chart, 1, chart.data[index].volume);
		let zeroY = getChartY(chart, 1, 0);
		if (mp.y >= Math.min(volY, zeroY) && mp.y <= Math.max(volY, zeroY)) {
			chart.selectShape = "VOL";
		}
	}
	else if (mp.y >= 0 && mp.y <= candleHeight) {
		let isTrend = chart.cycle == "trend";
		if (!isTrend) {
			if (chart.mainIndicator == "BOLL") {
				if (selectLines(chart, mp, 0, chart.bollMid, index)) {
					chart.selectShape = chart.mainIndicator;
					chart.selectShapeEx = "MID";
				}
				else if (selectLines(chart, mp, 0, chart.bollUp, index)) {
					chart.selectShape = chart.mainIndicator;
					chart.selectShapeEx = "UP";
				} else if (selectLines(chart, mp, 0, chart.bollDown, index)) {
					chart.selectShape = chart.mainIndicator;
					chart.selectShapeEx = "DOWN";
				}
			} else if (chart.mainIndicator == "MA") {
				if (selectLines(chart, mp, 0, chart.ma5, index)) {
					chart.selectShape = chart.mainIndicator;
					chart.selectShapeEx = "5";
				}
				else if (selectLines(chart, mp, 0, chart.ma10, index)) {
					chart.selectShape = chart.mainIndicator;
					chart.selectShapeEx = "10";
				}
				else if (selectLines(chart, mp, 0, chart.ma20, index)) {
					chart.selectShape = chart.mainIndicator;
					chart.selectShapeEx = "20";
				}
				else if (selectLines(chart, mp, 0, chart.ma30, index)) {
					chart.selectShape = chart.mainIndicator;
					chart.selectShapeEx = "30";
				}
				else if (selectLines(chart, mp, 0, chart.ma120, index)) {
					chart.selectShape = chart.mainIndicator;
					chart.selectShapeEx = "120";
				}
				else if (selectLines(chart, mp, 0, chart.ma250, index)) {
					chart.selectShape = chart.mainIndicator;
					chart.selectShapeEx = "250";
				}
			}
		}
		if (chart.selectShape == "") {
			let highY = getChartY(chart, 0, chart.data[index].high);
			let lowY = getChartY(chart, 0, chart.data[index].low);
			if (isTrend) {
				if (selectLines(chart, mp, 0, chart.closeArr, index)) {
					chart.selectShape = "CANDLE";
				}
			}
			else {
				if (mp.y >= Math.min(lowY, highY) && mp.y <= Math.max(lowY, highY)) {
					chart.selectShape = "CANDLE";
				}
			}
		}
	}
	if (chart.shapes.length > 0) {
		for (let i = 0; i < chart.shapes.length; i++) {
			let shape = chart.shapes[i];
			if (shape.leftOrRight) {
				if (selectLines(chart, mp, shape.divIndex, shape.datas, index)) {
					chart.selectShape = shape.shapeName;
					break;
				}
			} else {
				if (selectLinesInRight(chart, mp, shape.divIndex, shape.datas, index)) {
					chart.selectShape = shape.shapeName;
					break;
				}
			}
		}
	}
}

/*
* 触摸开始方法
* view:视图
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
*/
function onTouchBeginDefault(view : FCView, firstTouch : boolean, firstPoint : FCPoint, secondTouch : boolean, secondPoint : FCPoint) {
	if (view.viewType == "tree") {
		touchDownTree((view as any) as FCTree, firstTouch, firstPoint, secondTouch, secondPoint, 1);
	}
	else if (view.viewType == "grid") {
		touchDownGrid((view as any) as FCGrid, firstTouch, firstPoint, secondTouch, secondPoint, 1);
	}
	else if (view.viewType == "div" || view.viewType == "layout" || view.viewType == "menu") {
		touchDownDiv((view as any) as FCDiv, firstTouch, firstPoint, secondTouch, secondPoint, 1);
	}
	else if (view.viewType == "calendar") {
		clickCalendar((view as any) as FCCalendar, firstPoint);
	}
	else if (view.viewType == "button") {
		invalidateView(view);
	}else if (view.viewType == "chart") {
		touchDownChart((view as any) as FCChart, firstTouch, firstPoint, secondTouch, secondPoint);
	}
}

/*
* 触摸移动方法
* view:视图
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
*/
function onTouchMoveDefault(view : FCView, firstTouch : boolean, firstPoint : FCPoint, secondTouch : boolean, secondPoint : FCPoint) {
	if (view.viewType == "tree") {
		touchMoveTree((view as any) as FCTree, firstTouch, firstPoint, secondTouch, secondPoint);
		invalidateView(view);
	}
	else if (view.viewType == "grid") {
		touchMoveGrid((view as any) as FCGrid, firstTouch, firstPoint, secondTouch, secondPoint);
		invalidateView(view);
	}
	else if (view.viewType == "div" || view.viewType == "layout" || view.viewType == "menu") {
		touchMoveDiv((view as any) as FCDiv, firstTouch, firstPoint, secondTouch, secondPoint);
		invalidateView(view);
	}
	else if (view.viewType == "chart") {
		touchMoveChart((view as any) as FCChart, firstTouch, firstPoint, secondTouch, secondPoint);
		invalidateView(view);
	} else if (view.viewType == "menuitem") {
		touchMoveMenuItem((view as any) as FCMenuItem);
	}else{
		invalidateView(view);
	}
}

/*
* 触摸结束方法
* view:视图
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
*/
function onTouchEndDefault(view : FCView, firstTouch : boolean, firstPoint : FCPoint, secondTouch : boolean, secondPoint : FCPoint) {
	if (view.viewType == "tree") {
		touchUpTree((view as any) as FCTree, firstTouch, firstPoint, secondTouch, secondPoint, 1);
	}
	else if (view.viewType == "grid") {
		touchUpGrid((view as any) as FCGrid, firstTouch, firstPoint, secondTouch, secondPoint, 1);
	}
	else if (view.viewType == "div" || view.viewType == "layout" || view.viewType == "menu") {
		touchUpDiv((view as any) as FCDiv, firstTouch, firstPoint, secondTouch, secondPoint, 1);
	}
	else if (view.viewType == "chart") {
		let chart = (view as any) as FCChart;
		chart.firstTouchIndexCacheChart = -1;
		chart.secondTouchIndexCacheChart = -1;
	}
	invalidateView(view);
}

/*
* 鼠标点击实现方法
* view:视图
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
*/
function onClickDefault(view : FCView, firstTouch : boolean, firstPoint : FCPoint, secondTouch : boolean, secondPoint : FCPoint, clicks : number) {
	if (view.viewType == "tabbutton") {
		let tabView = view.parent as FCTabView;
		if (tabView.tabPages.length > 0) {
			for (let i = 0; i < tabView.tabPages.length; i++) {
				if (tabView.tabPages[i].headerButton == view) {
					selectTabPage(tabView, tabView.tabPages[i]);
					break
				}
			}
		}
		invalidateView(tabView);
	}
	else if (view.viewType == "radiobutton") {
		clickRadioButton(view as FCRadioButton, firstPoint);
		invalidate(view.paint!);
	}
	else if (view.viewType == "checkbox") {
		clickCheckBox(view as FCCheckBox, firstPoint);
		invalidateView(view.parent!);
	} else if (view.viewType == "menuitem") {
		clickMenuItem((view as any) as FCMenuItem);
	} else if (view.viewType == "combobox") {
		clickComboBox((view as any) as FCComboBox);
	}
}

/*
* 重绘背景的实现方法
* view:视图
* paint:绘图对象
* clipRect:裁剪区域
*/
function onPaintDefault(view : FCView, paint : FCPaint, clipRect : FCRect) {
	if (view.viewType == "chart") {
		drawChart(view as FCChart, paint, clipRect);
	}
	else if (view.viewType == "div" || view.viewType == "layout" || view.viewType == "tabpage") {
		drawDiv(view, paint, clipRect);
	}
	else if (view.viewType == "grid") {
		drawDiv(view, paint, clipRect);
		drawGrid((view as any) as FCGrid, paint, clipRect);
	}
	else if (view.viewType == "tree") {
		drawDiv(view, paint, clipRect);
		drawTree((view as any) as FCTree, paint, clipRect);
	}
	else if (view.viewType == "calendar") {
		drawCalendar(view as FCCalendar, paint);
	}
	else if (view.viewType == "label") {
		if (view.textColor != null && view.textColor != "none") {
			let tSize = paint.textSize(view.text, view.font);
			paint.drawText(view.text, view.textColor, view.font, 0, view.size.cy / 2 + 1 - tSize.cy / 2);
		}
	} else if (view.viewType == "textbox") {
		drawDiv(view, paint, clipRect);
		if (view.textColor != null && view.textColor != "none") {
			let tSize = paint.textSize(view.text, view.font);
			paint.drawText(view.text, view.textColor, view.font, 2, view.size.cy / 2 + 1 - tSize.cy / 2);
		}
	}
	else if (view.viewType == "radiobutton") {
		drawRadioButton(view as FCRadioButton, paint, clipRect)
	}
	else if (view.viewType == "checkbox") {
		drawCheckBox(view as FCCheckBox, paint, clipRect)
	} else if (view.viewType == "menuitem") {
		drawMenuItem((view as any) as FCMenuItem, paint, clipRect);
	} else if (view.viewType == "combobox") {
		drawComboBox((view as any) as FCComboBox, paint, clipRect);
	}
	else {
		drawButton(view, paint, clipRect)
	}
}

/*
* 重绘边框的实现方法
* view:视图
* paint:绘图对象
* clipRect:裁剪区域
*/
function onPaintBorderDefault(view : FCView, paint : FCPaint, clipRect : FCRect) {
	if (view.viewType == "grid") {
		drawGridScrollBar((view as any) as FCGrid, paint, clipRect);
		drawDivBorder(view, paint, clipRect);
	}
	else if (view.viewType == "tree") {
		drawTreeScrollBar((view as any) as FCTree, paint, clipRect);
		drawDivBorder(view, paint, clipRect);
	}
	else if (view.viewType == "div" || view.viewType == "layout" || view.viewType == "menu") {
		drawDivScrollBar((view as any) as FCDiv, paint, clipRect);
		drawDivBorder(view, paint, clipRect);
	}
	else if (view.viewType == "tabpage") {
		drawDivBorder(view, paint, clipRect);
	}
	else if (view.viewType == "tabview") {
		drawTabViewBorder((view as any) as FCTabView, paint, clipRect);
	} else if (view.viewType == "textbox") {
		drawDivBorder(view, paint, clipRect);
	}
}

export default {
	FCPoint,
	FCSize,
	FCRect,
	FCPadding,
	FCPaint,
	FCView,
	addView,
	addViewToParent,
	removeView,
	removeViewFromParent,
	clientX,
	clientY,
	containsPoint,
	findViewByName,
	findView,
	isPaintVisible,
	getIntersectRect ,
	renderViews,
	invalidate,
	invalidateView,
	updateViewDefault,
	FCButton,
	FCLabel,
	FCCheckBox,
	FCRadioButton,
	drawCheckBox,
	drawRadioButton,
	clickCheckBox,
	clickRadioButton,
	drawButton,
	SecurityData,
	BaseShape,
	FCPlot,
	FCChart,
	dateFormat,
	lineXY,
	selectLine,
	selectRay,
	selectSegment,
	ellipseOR,
	ellipseHasPoint,
	linearRegressionEquation,
	maxValue,
	minValue,
	avgValue,
	parallelogram,
	fibonacciValue,
	getPercentParams,
	getCandleRange,
	rectangleXYWH,
	selectPlot,
	touchMoveChart,
	getLRBandRange,
	getChartIndex,
	getChartMaxVisibleCount,
	getCandleDivHeight,
	getVolDivHeight,
	getIndDivHeight,
	getIndDivHeight2,
	getChartWorkAreaWidth,
	getChartX,
	getChartIndexByDate,
	getChartDateByIndex,
	getChartY,
	getChartYInRight,
	getChartValue,
	getCandleDivValue,
	checkChartLastVisibleIndex,
	resetChartVisibleRecord,
	setChartVisibleIndex,
	drawChart,
	chartGridScale,
	zoomOutChart,
	zoomInChart,
	drawChartScale,
	drawChartCrossLine,
	calculateChartMaxMin,
	drawChartLines,
	drawChartLinesInRight,
	drawChartPlot,
	drawChartStock,
	calcChartIndicator,
	getEMA,
	getMACD,
	getDIF,
	clearDataArr,
	getBollData,
	getKDJData,
	getRSIData,
	getRocData,
	getBIASData,
	getDMAData,
	getBBIData,
	getWRData,
	getCCIData,
	getTRIXData,
	selectLines,
	selectLinesInRight,
	selectShape,
	DayButton,
	MonthButton,
	YearButton,
	DayDiv,
	MonthDiv,
	YearDiv,
	HeadDiv,
	TimeDiv,
	CYear,
	CMonth,
	CDay,
	FCCalendar,
	getDaysInMonth,
	getMonthStr,
	getYear,
	showOrHideDayDiv,
	showOrHideMonthDiv,
	showOrHideYearDiv,
	initCalendar,
	dayOfWeek,
	getMonth,
	getNextMonth,
	getLastMonth,
	resetDayDiv,
	resetMonthDiv,
	resetYearDiv,
	selectStartYear,
	selectYear,
	selectDay,
	updateCalendar,
	drawHeadDiv,
	drawDayButton,
	drawMonthButton,
	drawYearButton,
	drawCalendar,
	clickDayButton,
	clickMonthButton,
	clickYearButton,
	clickLastButton,
	clickNextButton,
	clickModeButton,
	clickCalendar,
	FCDiv,
	drawDivScrollBar,
	getDivContentWidth,
	getDivContentHeight,
	touchMoveDiv,
	touchDownDiv,
	checkDragScroll_Div,
	touchUpDiv,
	touchWheelDiv,
	drawDiv,
	drawDivBorder,
	FCGridColumn,
	FCGridCell,
	FCGridRow,
	FCGrid,
	drawGridCell,
	drawGridColumn,
	drawGrid,
	drawGridScrollBar,
	getGridContentWidth,
	getGridContentHeight,
	touchMoveGrid,
	touchDownGrid,
	checkGridDragScroll,
	touchUpGrid,
	touchWheelGrid,
	FCTextBox,
	FCComboBox,
	FCLayoutDiv,
	resetLayoutDiv,
	FCSplitLayoutDiv,
	resetSplitLayoutDiv,
	FCTabView,
	FCTabPage,
	updataPageLayout,
	updateTabLayout,
	addTabPage,
	removeTabPage,
	selectTabPage,
	checkTabPageAnimation,
	drawTabViewBorder,
	FCTreeColumn,
	FCTreeNode,
	FCTreeRow,
	FCTree,
	getTotalIndent,
	drawTreeNode,
	drawTree,
	drawTreeScrollBar,
	getTreeContentWidth,
	getTreeContentHeight,
	touchMoveTree,
	touchDownTree,
	checkDragScroll_Tree,
	touchUpTree,
	updateTreeRowIndex,
	getTreeLastNodeRowIndex,
	appendTreeNode,
	removeTreeNode,
	hideOrShowTreeNode,
	checkOrUnCheckTreeNode,
	touchWheelTree,
	onClickDefault,
	onTouchBeginDefault,
	onTouchMoveDefault,
	onTouchEndDefault,
	onPaintDefault,
	onPaintBorderDefault,
	touchDownChart,
	addPlotDefault,
	adjustMenu,
	addMenuItem,
	addMenuItemToParent,
	checkShowMenu,
	closeMenus,
	touchMoveMenuItem,
	drawMenuItem,
	clickMenuItem,
	drawComboBox,
}